@@ -18,36 +18,39 @@ USING System.Reflection.Metadata
18
18
USING System.Reflection.PortableExecutable
19
19
USING ICSharpCode.Decompiler.CSharp.ProjectDecompiler
20
20
21
+ USING ICSharpCode.Decompiler.Solution
22
+ USING System.Threading
23
+
21
24
BEGIN NAMESPACE ILSpy.XSharpLanguage
22
25
23
26
[ExportAttribute( TYPEOF(Language) )] ;
24
27
PUBLIC CLASS XSharpLanguage INHERIT Language
25
-
26
-
28
+
29
+
27
30
CONSTRUCTOR ()
28
31
RETURN
29
-
30
- PUBLIC OVERRIDE PROPERTY Name AS STRING
32
+
33
+ PUBLIC OVERRIDE PROPERTY Name AS STRING
31
34
GET
32
35
RETURN "XSharp"
33
36
END GET
34
- END PROPERTY
37
+ END PROPERTY
35
38
36
39
37
- PUBLIC OVERRIDE PROPERTY FileExtension AS STRING
40
+ PUBLIC OVERRIDE PROPERTY FileExtension AS STRING
38
41
GET
39
42
// used in 'Save As' dialog
40
43
RETURN ".prg"
41
44
END GET
42
- END PROPERTY
45
+ END PROPERTY
43
46
44
- PUBLIC OVERRIDE PROPERTY ProjectFileExtension AS STRING
47
+ PUBLIC OVERRIDE PROPERTY ProjectFileExtension AS STRING
45
48
GET
46
49
RETURN ".xsproj"
47
50
END GET
48
- END PROPERTY
51
+ END PROPERTY
49
52
50
- PUBLIC OVERRIDE METHOD DecompileMethod ( methoddef AS IMethod, output AS ITextOutput, options AS DecompilationOptions) AS VOID
53
+ PUBLIC OVERRIDE METHOD DecompileMethod ( methoddef AS IMethod, output AS ITextOutput, options AS DecompilationOptions) AS VOID
51
54
LOCAL decompiler AS CSharpDecompiler
52
55
LOCAL assembly AS PEFile
53
56
LOCAL method2 AS IMethod
@@ -68,17 +71,17 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
68
71
ENDIF
69
72
SELF :WriteCode (output, options :DecompilerSettings , decompiler :Decompile(methoddef :MetadataToken ), decompiler :TypeSystem )
70
73
RETURN
71
-
72
- PUBLIC OVERRIDE METHOD DecompileProperty (propDef AS IProperty, output AS ITextOutput, options AS DecompilationOptions) AS VOID
74
+
75
+ PUBLIC OVERRIDE METHOD DecompileProperty (propDef AS IProperty, output AS ITextOutput, options AS DecompilationOptions) AS VOID
73
76
LOCAL decompiler AS CSharpDecompiler
74
77
LOCAL assembly AS PEFile
75
78
//
76
79
assembly := propDef :ParentModule :PEFile
77
80
decompiler := SELF :CreateDecompiler (assembly, options)
78
81
SELF :WriteCommentLine (output, SELF :TypeToString (propDef :DeclaringType , TRUE ))
79
82
SELF :WriteCode (output, options :DecompilerSettings , decompiler :Decompile(propDef :MetadataToken ), decompiler :TypeSystem )
80
-
81
- PUBLIC OVERRIDE METHOD DecompileField (fieldDef AS IField, output AS ITextOutput, options AS DecompilationOptions) AS VOID
83
+
84
+ PUBLIC OVERRIDE METHOD DecompileField (fieldDef AS IField, output AS ITextOutput, options AS DecompilationOptions) AS VOID
82
85
LOCAL assembly AS PEFile
83
86
LOCAL decompiler AS CSharpDecompiler
84
87
LOCAL definitions AS List< EntityHandle>
@@ -95,26 +98,26 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
95
98
definition := decompiler :TypeSystem :MainModule :GetDefinition((FieldDefinitionHandle)fieldDef :MetadataToken )
96
99
decompiler :AstTransforms :Add (SelectFieldTransform{definition})
97
100
SELF :WriteCode (output, options :DecompilerSettings , decompiler :Decompile(definitions), decompiler :TypeSystem )
98
-
99
- PUBLIC OVERRIDE METHOD DecompileType (typeDef AS ITypeDefinition, output AS ITextOutput, options AS DecompilationOptions) AS VOID
101
+
102
+ PUBLIC OVERRIDE METHOD DecompileType (typeDef AS ITypeDefinition, output AS ITextOutput, options AS DecompilationOptions) AS VOID
100
103
LOCAL assembly AS PEFile
101
104
LOCAL decompiler AS CSharpDecompiler
102
105
//
103
106
assembly := typeDef :ParentModule :PEFile
104
107
WriteCommentLine (output, SELF :TypeToString (typeDef, TRUE ))
105
108
decompiler := SELF :CreateDecompiler (assembly, options)
106
109
SELF :WriteCode (output, options :DecompilerSettings , decompiler :Decompile(typeDef :MetadataToken ), decompiler :TypeSystem )
107
-
108
- PUBLIC OVERRIDE METHOD DecompileEvent (evt AS IEvent , output AS ITextOutput , options AS DecompilationOptions ) AS VOID
110
+
111
+ PUBLIC OVERRIDE METHOD DecompileEvent (evt AS IEvent , output AS ITextOutput , options AS DecompilationOptions ) AS VOID
109
112
LOCAL assembly AS PEFile
110
113
LOCAL decompiler AS CSharpDecompiler
111
114
//
112
115
assembly := evt :ParentModule :PEFile
113
116
WriteCommentLine (output, SELF :TypeToString (evt :DeclaringType , TRUE ))
114
117
decompiler := SELF :CreateDecompiler (assembly, options)
115
118
SELF :WriteCode (output, options :DecompilerSettings , decompiler :Decompile(evt :MetadataToken ), decompiler :TypeSystem )
116
-
117
- PUBLIC OVERRIDE METHOD DecompileAssembly (asmbly AS LoadedAssembly , output AS ITextOutput , options AS DecompilationOptions ) AS ICSharpCode.Decompiler.Solution.ProjectId
119
+
120
+ PUBLIC OVERRIDE METHOD DecompileAssembly (asmbly AS LoadedAssembly , output AS ITextOutput , options AS DecompilationOptions ) AS ICSharpCode.Decompiler.Solution.ProjectId
118
121
// LOCAL result AS ModuleDefinition
119
122
// //LOCAL iLSpyWholeProjectDecompiler AS ILSpyWholeProjectDecompiler
120
123
// LOCAL moduleDefinition AS ModuleDefinition
@@ -237,8 +240,8 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
237
240
SELF :WriteCode ( output, options :DecompilerSettings , syntax, decompiler :TypeSystem )
238
241
//
239
242
RETURN NULL
240
-
241
-
243
+
244
+
242
245
PRIVATE METHOD WriteCode (output AS ITextOutput, settings AS DecompilerSettings, syntaxTree AS SyntaxTree, typeSystem AS IDecompilerTypeSystem) AS VOID
243
246
LOCAL visitor AS InsertParenthesesVisitor
244
247
LOCAL writer1 AS TextTokenWriter
@@ -261,9 +264,9 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
261
264
decoratedWriter := XSharpHighlightingTokenWriter{decoratedWriter, textOutput, xsSettings }
262
265
ENDIF
263
266
syntaxTree :AcceptVisitor(XSharpOutputVisitor{decoratedWriter, settings :CSharpFormattingOptions , typeSystem })
264
-
265
-
266
-
267
+
268
+
269
+
267
270
PRIVATE METHOD CreateDecompiler (module AS PEFile, options AS DecompilationOptions ) AS CSharpDecompiler
268
271
LOCAL decompiler AS CSharpDecompiler
269
272
//
@@ -275,40 +278,40 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
275
278
ENDDO
276
279
// decompiler:AstTransforms:Add( EscapeInvalidIdentifiers{})
277
280
RETURN decompiler
278
-
279
- // PUBLIC STATIC METHOD GetPlatformDisplayName(module AS PEFile ) AS STRING
280
- // LOCAL pEHeaders AS PEHeaders
281
- // LOCAL machine AS Machine
282
- // LOCAL characteristics AS Characteristics
283
- // LOCAL flags AS CorFlags
284
- // //
285
- // pEHeaders := module:Reader:PEHeaders
286
- // machine := pEHeaders:CoffHeader:Machine
287
- // characteristics := pEHeaders:CoffHeader:Characteristics
288
- // flags := pEHeaders:CorHeader:Flags
289
- // BEGIN SWITCH machine
290
- // CASE Machine.I386
291
- // IF ((flags & CorFlags.Prefers32Bit) != 0)
292
- // RETURN "AnyCPU (32-bit preferred)"
293
- // ENDIF
294
- // IF ((flags & CorFlags.Requires32Bit) != 0)
295
- // RETURN "x86"
296
- // ENDIF
297
- // IF (((flags & CorFlags.ILOnly) == (CorFlags)0) .AND. ((characteristics & Characteristics.Bit32Machine) != 0))
298
- // RETURN "x86"
299
- // ENDIF
300
- // RETURN "AnyCPU (64-bit preferred)"
301
- // CASE Machine.Amd64
302
- // RETURN "x64"
303
- // CASE Machine.IA64
304
- // RETURN "Itanium"
305
- // OTHERWISE
306
- // RETURN machine:ToString()
307
- // END SWITCH
308
-
309
- //PUBLIC STATIC METHOD GetRuntimeDisplayName(module AS PEFile ) AS STRING
310
- // RETURN module:Metadata:MetadataVersion
311
-
281
+
282
+ // PUBLIC STATIC METHOD GetPlatformDisplayName(module AS PEFile ) AS STRING
283
+ // LOCAL pEHeaders AS PEHeaders
284
+ // LOCAL machine AS Machine
285
+ // LOCAL characteristics AS Characteristics
286
+ // LOCAL flags AS CorFlags
287
+ // //
288
+ // pEHeaders := module:Reader:PEHeaders
289
+ // machine := pEHeaders:CoffHeader:Machine
290
+ // characteristics := pEHeaders:CoffHeader:Characteristics
291
+ // flags := pEHeaders:CorHeader:Flags
292
+ // BEGIN SWITCH machine
293
+ // CASE Machine.I386
294
+ // IF ((flags & CorFlags.Prefers32Bit) != 0)
295
+ // RETURN "AnyCPU (32-bit preferred)"
296
+ // ENDIF
297
+ // IF ((flags & CorFlags.Requires32Bit) != 0)
298
+ // RETURN "x86"
299
+ // ENDIF
300
+ // IF (((flags & CorFlags.ILOnly) == (CorFlags)0) .AND. ((characteristics & Characteristics.Bit32Machine) != 0))
301
+ // RETURN "x86"
302
+ // ENDIF
303
+ // RETURN "AnyCPU (64-bit preferred)"
304
+ // CASE Machine.Amd64
305
+ // RETURN "x64"
306
+ // CASE Machine.IA64
307
+ // RETURN "Itanium"
308
+ // OTHERWISE
309
+ // RETURN machine:ToString()
310
+ // END SWITCH
311
+
312
+ //PUBLIC STATIC METHOD GetRuntimeDisplayName(module AS PEFile ) AS STRING
313
+ // RETURN module:Metadata:MetadataVersion
314
+
312
315
PRIVATE STATIC METHOD CollectFieldsAndCtors (type AS ITypeDefinition , isStatic AS LOGIC ) AS List< EntityHandle>
313
316
LOCAL list AS List< EntityHandle>
314
317
LOCAL metadataToken AS EntityHandle
@@ -375,19 +378,19 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
375
378
376
379
377
380
*/
378
- END CLASS
379
-
380
-
381
-
381
+ END CLASS
382
+
383
+
384
+
382
385
CLASS SelectCtorTransform IMPLEMENTS IAstTransform
383
386
PRIVATE INITONLY ctor AS IMethod
384
387
PRIVATE INITONLY removedSymbols := HashSet< ISymbol> {} AS HashSet< ISymbol>
385
388
386
389
387
390
PUBLIC CONSTRUCTOR (ctor AS IMethod )
388
391
SELF :ctor := ctor
389
-
390
-
392
+
393
+
391
394
PUBLIC METHOD Run (rootNode AS AstNode , context AS TransformContext ) AS VOID
392
395
LOCAL ctorDeclaration AS ConstructorDeclaration
393
396
LOCAL currentAstNode AS AstNode
@@ -439,16 +442,16 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
439
442
NEXT
440
443
441
444
442
- END CLASS
443
-
444
-
445
+ END CLASS
446
+
447
+
445
448
CLASS SelectFieldTransform IMPLEMENTS IAstTransform
446
449
PRIVATE INITONLY fld AS IField
447
450
448
451
PUBLIC CONSTRUCTOR (fld AS IField )
449
452
SELF :fld := fld
450
-
451
-
453
+
454
+
452
455
PUBLIC METHOD Run (rootNode AS AstNode , context AS TransformContext ) AS VOID
453
456
LOCAL currentAstNode AS AstNode
454
457
LOCAL entityDeclaration1 AS EntityDeclaration
@@ -476,9 +479,9 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
476
479
NEXT
477
480
478
481
479
- END CLASS
480
-
481
-
482
+ END CLASS
483
+
484
+
482
485
CLASS XSharpWholeProjectDecompiler INHERIT WholeProjectDecompiler
483
486
PRIVATE INITONLY assembly AS LoadedAssembly
484
487
PRIVATE INITONLY options AS DecompilationOptions
@@ -487,9 +490,9 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
487
490
SUPER (options :DecompilerSettings , assembly :GetAssemblyResolver(), assembly :GetDebugInfoOrNull() )
488
491
SELF :assembly := assembly
489
492
SELF :options := options
490
-
491
-
492
- PROTECTED OVERRIDE METHOD WriteResourceToFile (fileName AS STRING , resourceName AS STRING , entryStream AS Stream ) AS IEnumerable< ValueTuple< STRING, STRING>>
493
+
494
+
495
+ PROTECTED OVERRIDE METHOD WriteResourceToFile (fileName AS STRING , resourceName AS STRING , entryStream AS Stream ) AS IEnumerable< ValueTuple< STRING, STRING>>
493
496
//
494
497
FOREACH exportedValue AS IResourceFileHandler IN App.ExportProvider :GetExportedValues < IResourceFileHandler> ()
495
498
IF (exportedValue :CanHandle(fileName, SELF :options))
@@ -500,9 +503,69 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
500
503
ENDIF
501
504
NEXT
502
505
RETURN SUPER :WriteResourceToFile(fileName, resourceName, entryStream)
506
+
507
+
508
+ PUBLIC METHOD DecompileProject (moduleDefinition AS PEFile , targetDirectory AS STRING , projectFileWriter AS TextWriter , cancellationToken := DEFAULT (CancellationToken) AS CancellationToken ) AS ProjectId
509
+ LOCAL list AS List< Tuple< STRING, STRING>>
510
+ //
511
+ IF string.IsNullOrEmpty (targetDirectory)
512
+ THROW InvalidOperationException{e"Must set TargetDirectory" }
513
+ ENDIF
514
+ SELF :targetDirectory := targetDirectory
515
+ SELF :directories :Clear()
516
+ list := Enumerable.ToList< Tuple< STRING, STRING>> (SELF :xsWriteCodeFilesInProject (moduleDefinition, cancellationToken))
517
+ list :AddRange(SELF :WriteResourceFilesInProject (moduleDefinition))
518
+ IF SELF :StrongNameKeyFile != NULL
519
+ @@ File.Copy (SELF :StrongNameKeyFile, Path .Combine (targetDirectory, Path .GetFileName (SELF :StrongNameKeyFile)))
520
+ ENDIF
521
+ RETURN SELF :WriteProjectFile (projectFileWriter, list, moduleDefinition)
522
+
523
+
524
+ PRIVATE METHOD xsWriteCodeFilesInProject (module AS PEFile , cancellationToken AS CancellationToken ) AS IEnumerable< Tuple< STRING, STRING>>
525
+ LOCAL metadata AS MetadataReader
526
+ LOCAL list AS List< IGrouping< STRING, TypeDefinitionHandle>>
527
+ LOCAL ts AS DecompilerTypeSystem
528
+ LOCAL val AS ParallelOptions
529
+ //
530
+ metadata := module :Metadata
531
+ list := Enumerable.ToList< IGrouping< STRING, TypeDefinitionHandle>> (Enumerable.GroupBy< TypeDefinitionHandle, STRING> (Enumerable.Where< TypeDefinitionHandle> (module :Metadata :GetTopLevelTypeDefinitions (), (@@ Func< TypeDefinitionHandle, LOGIC> )({td AS TypeDefinitionHandle => SELF :IncludeTypeWhenDecompilingProject (module, td)})), (@@ Func< TypeDefinitionHandle, STRING> ){
532
+ (h AS TypeDefinitionHandle ) =>
533
+ typeDefinition := metadata :GetTypeDefinition(h)
534
+ text := CleanUpFileName (metadata :GetString(typeDefinition :Name )) + ".cs"
535
+ IF string.IsNullOrEmpty (metadata :GetString(typeDefinition :Namespace ))
536
+ RETURN text
537
+ ENDIF
538
+ text2 := CleanUpFileName (metadata :GetString(typeDefinition :Namespace ))
539
+ IF SELF :directories :Add(text2)
540
+ Directory.CreateDirectory (Path .Combine (SELF :targetDirectory, text2))
541
+ ENDIF
542
+ RETURN Path .Combine (text2, text)
543
+ },
544
+ (IEqualityComparer< STRING> )StringComparer.OrdinalIgnoreCase))
545
+ //
546
+ ts := DecompilerTypeSystem{module, SELF :AssemblyResolver, SELF :settings}
547
+ val := ParallelOptions{}
548
+ val :set_MaxDegreeOfParallelism(SELF :MaxDegreeOfParallelism)
549
+ val :set_CancellationToken(cancellationToken)
550
+ Parallel.ForEach< IGrouping< STRING, TypeDefinitionHandle>> ((IEnumerable< IGrouping< STRING, TypeDefinitionHandle>> )list, val, (Action< IGrouping< STRING, TypeDefinitionHandle>> ){(@@ file AS IGrouping< STRING, TypeDefinitionHandle> ) =>
551
+ val2 := StreamWriter{Path .Combine (SELF :targetDirectory, @@ file :get_Key())}
552
+ TRY
553
+ cSharpDecompiler := SELF :CreateDecompiler (ts)
554
+ cSharpDecompiler :CancellationToken := cancellationToken
555
+ syntaxTree := cSharpDecompiler :DecompileTypes (Enumerable.ToArray< TypeDefinitionHandle> ((IEnumerable< TypeDefinitionHandle> )@@ file))
556
+ syntaxTree :AcceptVisitor(CSharpOutputVisitor{(TextWriter)(OBJECT)val2, SELF :settings :CSharpFormattingOptions })
557
+
558
+ CATCH ex AS Exception WHEN ((! (ex IS OperationCanceledException)) .AND. (! (ex IS DecompilerException)))
559
+ THROW DecompilerException{module, "Error decompiling for '" + @@ file :get_Key() + e"'" , ex}
560
+
561
+ FINALLY
562
+ ((IDisposable)val2)?:Dispose ()
563
+ END TRY
564
+ })
565
+ RETURN Enumerable.Concat< Tuple< STRING, STRING>> (Enumerable.Select < IGrouping< STRING, TypeDefinitionHandle> , Tuple< STRING, STRING>> ((IEnumerable< IGrouping< STRING, TypeDefinitionHandle>> )list, (@@ Func< IGrouping< STRING, TypeDefinitionHandle> , Tuple< STRING, STRING>> )({f AS IGrouping< STRING, TypeDefinitionHandle> => Tuple.Create (e"Compile" , f :get_Key())})), SELF :WriteAssemblyInfo (ts, cancellationToken))
503
566
504
567
505
568
END CLASS
506
-
507
-
569
+
570
+
508
571
END NAMESPACE
0 commit comments