Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
894f233e
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
894f233e
编写于
12月 01, 2020
作者:
F
Fredric Silberberg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Optimize BindInterpolatedString for the empty string cases, fix up tests.
上级
8f123bc6
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
107 addition
and
94 deletion
+107
-94
src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs
...ilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs
+93
-88
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IInterpolatedStringExpression.cs
...peration/IOperationTests_IInterpolatedStringExpression.cs
+2
-2
src/Compilers/CSharp/Test/Semantic/Semantics/ConstantTests.cs
...Compilers/CSharp/Test/Semantic/Semantics/ConstantTests.cs
+12
-4
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_InterpolatedString.cs
浏览文件 @
894f233e
...
...
@@ -16,117 +16,122 @@ private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSynta
{
var
builder
=
ArrayBuilder
<
BoundExpression
>.
GetInstance
();
var
stringType
=
GetSpecialType
(
SpecialType
.
System_String
,
diagnostics
,
node
);
var
objectType
=
GetSpecialType
(
SpecialType
.
System_Object
,
diagnostics
,
node
);
var
intType
=
GetSpecialType
(
SpecialType
.
System_Int32
,
diagnostics
,
node
);
ConstantValue
?
resultConstant
=
null
;
bool
isResultConstant
=
true
;
foreach
(
var
content
in
node
.
Contents
)
if
(
node
.
Contents
.
Count
==
0
)
{
switch
(
content
.
Kind
())
resultConstant
=
ConstantValue
.
Create
(
string
.
Empty
);
}
else
{
var
objectType
=
GetSpecialType
(
SpecialType
.
System_Object
,
diagnostics
,
node
);
var
intType
=
GetSpecialType
(
SpecialType
.
System_Int32
,
diagnostics
,
node
);
foreach
(
var
content
in
node
.
Contents
)
{
case
SyntaxKind
.
Interpolation
:
{
var
interpolation
=
(
InterpolationSyntax
)
content
;
var
value
=
BindValue
(
interpolation
.
Expression
,
diagnostics
,
BindValueKind
.
RValue
);
if
(
value
.
Type
is
null
)
{
value
=
GenerateConversionForAssignment
(
objectType
,
value
,
diagnostics
);
}
else
switch
(
content
.
Kind
())
{
case
SyntaxKind
.
Interpolation
:
{
value
=
BindToNaturalType
(
value
,
diagnostics
);
_
=
GenerateConversionForAssignment
(
objectType
,
value
,
diagnostics
);
}
// We need to ensure the argument is not a lambda, method group, etc. It isn't nice to wait until lowering,
// when we perform overload resolution, to report a problem. So we do that check by calling
// GenerateConversionForAssignment with objectType. However we want to preserve the original expression's
// natural type so that overload resolution may select a specialized implementation of string.Format,
// so we discard the result of that call and only preserve its diagnostics.
BoundExpression
?
alignment
=
null
;
BoundLiteral
?
format
=
null
;
if
(
interpolation
.
AlignmentClause
!=
null
)
{
alignment
=
GenerateConversionForAssignment
(
intType
,
BindValue
(
interpolation
.
AlignmentClause
.
Value
,
diagnostics
,
Binder
.
BindValueKind
.
RValue
),
diagnostics
);
var
alignmentConstant
=
alignment
.
ConstantValue
;
if
(
alignmentConstant
!=
null
&&
!
alignmentConstant
.
IsBad
)
var
interpolation
=
(
InterpolationSyntax
)
content
;
var
value
=
BindValue
(
interpolation
.
Expression
,
diagnostics
,
BindValueKind
.
RValue
);
if
(
value
.
Type
is
null
)
{
const
int
magnitudeLimit
=
32767
;
// check that the magnitude of the alignment is "in range".
int
alignmentValue
=
alignmentConstant
.
Int32Value
;
// We do the arithmetic using negative numbers because the largest negative int has no corresponding positive (absolute) value.
alignmentValue
=
(
alignmentValue
>
0
)
?
-
alignmentValue
:
alignmentValue
;
if
(
alignmentValue
<
-
magnitudeLimit
)
{
diagnostics
.
Add
(
ErrorCode
.
WRN_AlignmentMagnitude
,
alignment
.
Syntax
.
Location
,
alignmentConstant
.
Int32Value
,
magnitudeLimit
);
}
value
=
GenerateConversionForAssignment
(
objectType
,
value
,
diagnostics
);
}
else
if
(!
alignment
.
HasErrors
)
else
{
diagnostics
.
Add
(
ErrorCode
.
ERR_ConstantExpected
,
interpolation
.
AlignmentClause
.
Value
.
Location
);
value
=
BindToNaturalType
(
value
,
diagnostics
);
_
=
GenerateConversionForAssignment
(
objectType
,
value
,
diagnostics
);
}
}
if
(
interpolation
.
FormatClause
!=
null
)
{
var
text
=
interpolation
.
FormatClause
.
FormatStringToken
.
ValueText
;
char
lastChar
;
bool
hasErrors
=
false
;
if
(
text
.
Length
==
0
)
// We need to ensure the argument is not a lambda, method group, etc. It isn't nice to wait until lowering,
// when we perform overload resolution, to report a problem. So we do that check by calling
// GenerateConversionForAssignment with objectType. However we want to preserve the original expression's
// natural type so that overload resolution may select a specialized implementation of string.Format,
// so we discard the result of that call and only preserve its diagnostics.
BoundExpression
?
alignment
=
null
;
BoundLiteral
?
format
=
null
;
if
(
interpolation
.
AlignmentClause
!=
null
)
{
diagnostics
.
Add
(
ErrorCode
.
ERR_EmptyFormatSpecifier
,
interpolation
.
FormatClause
.
Location
);
hasErrors
=
true
;
alignment
=
GenerateConversionForAssignment
(
intType
,
BindValue
(
interpolation
.
AlignmentClause
.
Value
,
diagnostics
,
Binder
.
BindValueKind
.
RValue
),
diagnostics
);
var
alignmentConstant
=
alignment
.
ConstantValue
;
if
(
alignmentConstant
!=
null
&&
!
alignmentConstant
.
IsBad
)
{
const
int
magnitudeLimit
=
32767
;
// check that the magnitude of the alignment is "in range".
int
alignmentValue
=
alignmentConstant
.
Int32Value
;
// We do the arithmetic using negative numbers because the largest negative int has no corresponding positive (absolute) value.
alignmentValue
=
(
alignmentValue
>
0
)
?
-
alignmentValue
:
alignmentValue
;
if
(
alignmentValue
<
-
magnitudeLimit
)
{
diagnostics
.
Add
(
ErrorCode
.
WRN_AlignmentMagnitude
,
alignment
.
Syntax
.
Location
,
alignmentConstant
.
Int32Value
,
magnitudeLimit
);
}
}
else
if
(!
alignment
.
HasErrors
)
{
diagnostics
.
Add
(
ErrorCode
.
ERR_ConstantExpected
,
interpolation
.
AlignmentClause
.
Value
.
Location
);
}
}
else
if
(
SyntaxFacts
.
IsWhitespace
(
lastChar
=
text
[
text
.
Length
-
1
])
||
SyntaxFacts
.
IsNewLine
(
lastChar
))
if
(
interpolation
.
FormatClause
!=
null
)
{
diagnostics
.
Add
(
ErrorCode
.
ERR_TrailingWhitespaceInFormatSpecifier
,
interpolation
.
FormatClause
.
Location
);
hasErrors
=
true
;
}
var
text
=
interpolation
.
FormatClause
.
FormatStringToken
.
ValueText
;
char
lastChar
;
bool
hasErrors
=
false
;
if
(
text
.
Length
==
0
)
{
diagnostics
.
Add
(
ErrorCode
.
ERR_EmptyFormatSpecifier
,
interpolation
.
FormatClause
.
Location
);
hasErrors
=
true
;
}
else
if
(
SyntaxFacts
.
IsWhitespace
(
lastChar
=
text
[
text
.
Length
-
1
])
||
SyntaxFacts
.
IsNewLine
(
lastChar
))
{
diagnostics
.
Add
(
ErrorCode
.
ERR_TrailingWhitespaceInFormatSpecifier
,
interpolation
.
FormatClause
.
Location
);
hasErrors
=
true
;
}
format
=
new
BoundLiteral
(
interpolation
.
FormatClause
,
ConstantValue
.
Create
(
text
),
stringType
,
hasErrors
);
}
format
=
new
BoundLiteral
(
interpolation
.
FormatClause
,
ConstantValue
.
Create
(
text
),
stringType
,
hasErrors
);
}
builder
.
Add
(
new
BoundStringInsert
(
interpolation
,
value
,
alignment
,
format
,
null
));
if
(
value
.
ConstantValue
==
null
||
!(
interpolation
is
{
FormatClause
:
null
,
AlignmentClause
:
null
})
||
!(
value
.
ConstantValue
is
{
IsString
:
true
,
IsBad
:
false
}))
{
isResultConstant
=
false
;
builder
.
Add
(
new
BoundStringInsert
(
interpolation
,
value
,
alignment
,
format
,
null
));
if
(!
isResultConstant
||
value
.
ConstantValue
==
null
||
!(
interpolation
is
{
FormatClause
:
null
,
AlignmentClause
:
null
})
||
!(
value
.
ConstantValue
is
{
IsString
:
true
,
IsBad
:
false
}))
{
isResultConstant
=
false
;
continue
;
}
resultConstant
=
(
resultConstant
is
null
)
?
value
.
ConstantValue
:
FoldStringConcatenation
(
BinaryOperatorKind
.
StringConcatenation
,
resultConstant
,
value
.
ConstantValue
);
continue
;
}
resultConstant
=
(
resultConstant
is
null
)
?
value
.
ConstantValue
:
FoldStringConcatenation
(
BinaryOperatorKind
.
StringConcatenation
,
resultConstant
,
value
.
ConstantValue
);
continue
;
}
case
SyntaxKind
.
InterpolatedStringText
:
{
var
text
=
((
InterpolatedStringTextSyntax
)
content
).
TextToken
.
ValueText
;
builder
.
Add
(
new
BoundLiteral
(
content
,
ConstantValue
.
Create
(
text
,
SpecialType
.
System_String
),
stringType
));
if
(
isResultConstant
)
case
SyntaxKind
.
InterpolatedStringText
:
{
var
constantVal
=
ConstantValue
.
Create
(
ConstantValueUtils
.
UnescapeInterpolatedStringLiteral
(
text
),
SpecialType
.
System_String
);
resultConstant
=
(
resultConstant
is
null
)
?
constantVal
:
FoldStringConcatenation
(
BinaryOperatorKind
.
StringConcatenation
,
resultConstant
,
constantVal
);
var
text
=
((
InterpolatedStringTextSyntax
)
content
).
TextToken
.
ValueText
;
builder
.
Add
(
new
BoundLiteral
(
content
,
ConstantValue
.
Create
(
text
,
SpecialType
.
System_String
),
stringType
));
if
(
isResultConstant
)
{
var
constantVal
=
ConstantValue
.
Create
(
ConstantValueUtils
.
UnescapeInterpolatedStringLiteral
(
text
),
SpecialType
.
System_String
);
resultConstant
=
(
resultConstant
is
null
)
?
constantVal
:
FoldStringConcatenation
(
BinaryOperatorKind
.
StringConcatenation
,
resultConstant
,
constantVal
);
}
continue
;
}
continue
;
}
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
content
.
Kind
());
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
content
.
Kind
());
}
}
}
if
(!
isResultConstant
)
{
resultConstant
=
null
;
}
else
if
(
resultConstant
==
null
)
{
Debug
.
Assert
(
node
.
Contents
.
Count
==
0
);
resultConstant
=
ConstantValue
.
Create
(
string
.
Empty
);
if
(!
isResultConstant
)
{
resultConstant
=
null
;
}
}
Debug
.
Assert
(
isResultConstant
==
(
resultConstant
!=
null
));
return
new
BoundInterpolatedString
(
node
,
builder
.
ToImmutableAndFree
(),
resultConstant
,
stringType
);
}
}
...
...
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IInterpolatedStringExpression.cs
浏览文件 @
894f233e
...
...
@@ -29,7 +29,7 @@ public void M()
}
"
;
string
expectedOperationTree
=
@"
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""""')
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String
, Constant: """"
) (Syntax: '$""""')
Parts(0)
"
;
var
expectedDiagnostics
=
DiagnosticDescription
.
None
;
...
...
@@ -477,7 +477,7 @@ public void M(string p)
Left:
IParameterReferenceOperation: p (OperationKind.ParameterReference, Type: System.String) (Syntax: 'p')
Right:
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String) (Syntax: '$""""')
IInterpolatedStringOperation (OperationKind.InterpolatedString, Type: System.String
, Constant: """"
) (Syntax: '$""""')
Parts(0)
Next (Regular) Block[B2]
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/ConstantTests.cs
浏览文件 @
894f233e
...
...
@@ -3760,12 +3760,20 @@ void M2(string S1 = $""Testing"", object O = null, Namae N = null)
[
Fact
]
public
void
EmptyConstInterpolatedString
()
{
C
reateCompilation
(
@"
class C
C
ompileAndVerify
(
@"
public
class C
{
const string s = $"""";
public const string s = $"""";
static void Main()
{
System.Console.WriteLine(s);
}
}
"
,
parseOptions
:
TestOptions
.
RegularPreview
).
VerifyDiagnostics
();
"
,
parseOptions
:
TestOptions
.
RegularPreview
,
expectedOutput
:
""
,
symbolValidator
:
module
=>
{
Assert
.
Equal
(
string
.
Empty
,
module
.
GlobalNamespace
.
GetTypeMember
(
"C"
).
GetField
(
"s"
).
ConstantValue
);
});
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录