Browse Source

Fix bug in StringInterpolation transform: do not transform if arguments use string literals, nested string literals are not allowed.

pull/1012/head
Siegfried Pammer 8 years ago
parent
commit
f59504bbce
  1. 15
      ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
  2. 1
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs
  3. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il
  4. 19
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il
  5. 3
      ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

15
ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs

@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.CodeDom.Compiler; using System.CodeDom.Compiler;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -254,7 +255,7 @@ namespace ICSharpCode.Decompiler.Tests
try { try {
outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options, outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options,
outputFileName: Path.Combine(TestCasePath, testOutputFileName)); outputFileName: Path.Combine(TestCasePath, testOutputFileName));
string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly); string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, GetSettings(options));
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options); decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile); Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile);
@ -276,7 +277,7 @@ namespace ICSharpCode.Decompiler.Tests
try { try {
outputFile = Tester.AssembleIL(Path.Combine(TestCasePath, testFileName), asmOptions); outputFile = Tester.AssembleIL(Path.Combine(TestCasePath, testFileName), asmOptions);
string decompiledCodeFile = Tester.DecompileCSharp(outputFile); string decompiledCodeFile = Tester.DecompileCSharp(outputFile, GetSettings(options));
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options); decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
Tester.RunAndCompareOutput(testFileName, outputFile, decompiledOutputFile.PathToAssembly, decompiledCodeFile); Tester.RunAndCompareOutput(testFileName, outputFile, decompiledOutputFile.PathToAssembly, decompiledCodeFile);
@ -288,5 +289,15 @@ namespace ICSharpCode.Decompiler.Tests
decompiledOutputFile.TempFiles.Delete(); decompiledOutputFile.TempFiles.Delete();
} }
} }
DecompilerSettings GetSettings(CompilerOptions options)
{
if (!options.HasFlag(CompilerOptions.UseRoslyn)) {
return new DecompilerSettings {
StringInterpolation = false
};
}
return new DecompilerSettings();
}
} }
} }

1
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs

@ -38,6 +38,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(string.Format("{}", args.Length)); Console.WriteLine(string.Format("{}", args.Length));
Console.WriteLine(string.Format("{0:}", args.Length)); Console.WriteLine(string.Format("{0:}", args.Length));
Console.WriteLine(string.Format("{0{a}0}", args.Length)); Console.WriteLine(string.Format("{0{a}0}", args.Length));
Console.WriteLine(string.Format("test: {0}", string.Join(",", args)));
} }
} }
} }

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il

@ -25,14 +25,14 @@
.ver 0:0:0:0 .ver 0:0:0:0
} }
.module CS6_StringInterpolation.dll .module CS6_StringInterpolation.dll
// MVID: {12BAF781-868E-4161-A197-F81DC457D96B} // MVID: {F5FD4CCF-66AB-4E03-8E45-96F42947A65D}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000 .imagebase 0x10000000
.file alignment 0x00000200 .file alignment 0x00000200
.stackreserve 0x00100000 .stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI .subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY .corflags 0x00000001 // ILONLY
// Image base: 0x03620000 // Image base: 0x03070000
// =============== CLASS MEMBERS DECLARATION =================== // =============== CLASS MEMBERS DECLARATION ===================
@ -115,8 +115,8 @@
.method public hidebysig static void Invalid(string[] args) cil managed .method public hidebysig static void Invalid(string[] args) cil managed
{ {
// Code size 530 (0x212) // Code size 556 (0x22c)
.maxstack 2 .maxstack 3
IL_0000: ldstr "" IL_0000: ldstr ""
IL_0005: ldarg.0 IL_0005: ldarg.0
IL_0006: ldlen IL_0006: ldlen
@ -301,7 +301,15 @@
IL_0207: call string [mscorlib]System.String::Format(string, IL_0207: call string [mscorlib]System.String::Format(string,
object) object)
IL_020c: call void [mscorlib]System.Console::WriteLine(string) IL_020c: call void [mscorlib]System.Console::WriteLine(string)
IL_0211: ret IL_0211: ldstr "test: {0}"
IL_0216: ldstr ","
IL_021b: ldarg.0
IL_021c: call string [mscorlib]System.String::Join(string,
string[])
IL_0221: call string [mscorlib]System.String::Format(string,
object)
IL_0226: call void [mscorlib]System.Console::WriteLine(string)
IL_022b: ret
} // end of method CS6_StringInterpolation::Invalid } // end of method CS6_StringInterpolation::Invalid
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname

19
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il

@ -25,14 +25,14 @@
.ver 0:0:0:0 .ver 0:0:0:0
} }
.module CS6_StringInterpolation.dll .module CS6_StringInterpolation.dll
// MVID: {97DDF3A3-A5BD-433E-B982-F6DD427CE8FF} // MVID: {FE9286DD-8C20-4FC8-8786-543E572641EA}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000 .imagebase 0x10000000
.file alignment 0x00000200 .file alignment 0x00000200
.stackreserve 0x00100000 .stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI .subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY .corflags 0x00000001 // ILONLY
// Image base: 0x03970000 // Image base: 0x03840000
// =============== CLASS MEMBERS DECLARATION =================== // =============== CLASS MEMBERS DECLARATION ===================
@ -121,8 +121,8 @@
.method public hidebysig static void Invalid(string[] args) cil managed .method public hidebysig static void Invalid(string[] args) cil managed
{ {
// Code size 554 (0x22a) // Code size 581 (0x245)
.maxstack 2 .maxstack 3
IL_0000: nop IL_0000: nop
IL_0001: ldstr "" IL_0001: ldstr ""
IL_0006: ldarg.0 IL_0006: ldarg.0
@ -331,7 +331,16 @@
object) object)
IL_0223: call void [mscorlib]System.Console::WriteLine(string) IL_0223: call void [mscorlib]System.Console::WriteLine(string)
IL_0228: nop IL_0228: nop
IL_0229: ret IL_0229: ldstr "test: {0}"
IL_022e: ldstr ","
IL_0233: ldarg.0
IL_0234: call string [mscorlib]System.String::Join(string,
string[])
IL_0239: call string [mscorlib]System.String::Format(string,
object)
IL_023e: call void [mscorlib]System.Console::WriteLine(string)
IL_0243: nop
IL_0244: ret
} // end of method CS6_StringInterpolation::Invalid } // end of method CS6_StringInterpolation::Invalid
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname

3
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

@ -110,7 +110,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
break; break;
case "System.String.Format": case "System.String.Format":
if (context.Settings.StringInterpolation && arguments.Length > 1 if (context.Settings.StringInterpolation && arguments.Length > 1
&& arguments[0] is PrimitiveExpression stringExpression && stringExpression.Value is string) && arguments[0] is PrimitiveExpression stringExpression && stringExpression.Value is string
&& arguments.Skip(1).All(a => !a.DescendantsAndSelf.OfType<PrimitiveExpression>().Any(p => p.Value is string)))
{ {
var tokens = new List<(TokenKind, int, string)>(); var tokens = new List<(TokenKind, int, string)>();
int i = 0; int i = 0;

Loading…
Cancel
Save