Skip to content

Commit dfd2563

Browse files
committed
Correcting "Continue" genration instead of "Loop"; Added DecompileProject;
1 parent 0ab3a64 commit dfd2563

File tree

4 files changed

+145
-81
lines changed

4 files changed

+145
-81
lines changed

ILSpy.XSharpLanguage/XSharpHighlightingTokenWriter.prg

+1
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
481481
CASE "yield"
482482
CASE "return"
483483
CASE "exit"
484+
case "loop"
484485
color := gotoKeywordsColor
485486
END SWITCH
486487
//

ILSpy.XSharpLanguage/XSharpLanguage.prg

+141-78
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,39 @@ USING System.Reflection.Metadata
1818
USING System.Reflection.PortableExecutable
1919
USING ICSharpCode.Decompiler.CSharp.ProjectDecompiler
2020

21+
USING ICSharpCode.Decompiler.Solution
22+
USING System.Threading
23+
2124
BEGIN NAMESPACE ILSpy.XSharpLanguage
2225

2326
[ExportAttribute( TYPEOF(Language) )];
2427
PUBLIC CLASS XSharpLanguage INHERIT Language
25-
26-
28+
29+
2730
CONSTRUCTOR()
2831
RETURN
29-
30-
PUBLIC OVERRIDE PROPERTY Name AS STRING
32+
33+
PUBLIC OVERRIDE PROPERTY Name AS STRING
3134
GET
3235
RETURN "XSharp"
3336
END GET
34-
END PROPERTY
37+
END PROPERTY
3538

3639

37-
PUBLIC OVERRIDE PROPERTY FileExtension AS STRING
40+
PUBLIC OVERRIDE PROPERTY FileExtension AS STRING
3841
GET
3942
// used in 'Save As' dialog
4043
RETURN ".prg"
4144
END GET
42-
END PROPERTY
45+
END PROPERTY
4346

44-
PUBLIC OVERRIDE PROPERTY ProjectFileExtension AS STRING
47+
PUBLIC OVERRIDE PROPERTY ProjectFileExtension AS STRING
4548
GET
4649
RETURN ".xsproj"
4750
END GET
48-
END PROPERTY
51+
END PROPERTY
4952

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
5154
LOCAL decompiler AS CSharpDecompiler
5255
LOCAL assembly AS PEFile
5356
LOCAL method2 AS IMethod
@@ -68,17 +71,17 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
6871
ENDIF
6972
SELF:WriteCode(output, options:DecompilerSettings, decompiler:Decompile(methoddef:MetadataToken), decompiler:TypeSystem)
7073
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
7376
LOCAL decompiler AS CSharpDecompiler
7477
LOCAL assembly AS PEFile
7578
//
7679
assembly := propDef:ParentModule:PEFile
7780
decompiler := SELF:CreateDecompiler(assembly, options)
7881
SELF:WriteCommentLine(output, SELF:TypeToString(propDef:DeclaringType, TRUE))
7982
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
8285
LOCAL assembly AS PEFile
8386
LOCAL decompiler AS CSharpDecompiler
8487
LOCAL definitions AS List<EntityHandle>
@@ -95,26 +98,26 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
9598
definition := decompiler:TypeSystem:MainModule:GetDefinition((FieldDefinitionHandle)fieldDef:MetadataToken)
9699
decompiler:AstTransforms:Add(SelectFieldTransform{definition})
97100
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
100103
LOCAL assembly AS PEFile
101104
LOCAL decompiler AS CSharpDecompiler
102105
//
103106
assembly := typeDef:ParentModule:PEFile
104107
WriteCommentLine(output, SELF:TypeToString(typeDef, TRUE))
105108
decompiler := SELF:CreateDecompiler(assembly, options)
106109
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
109112
LOCAL assembly AS PEFile
110113
LOCAL decompiler AS CSharpDecompiler
111114
//
112115
assembly := evt:ParentModule:PEFile
113116
WriteCommentLine(output, SELF:TypeToString(evt:DeclaringType, TRUE))
114117
decompiler := SELF:CreateDecompiler(assembly, options)
115118
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
118121
// LOCAL result AS ModuleDefinition
119122
// //LOCAL iLSpyWholeProjectDecompiler AS ILSpyWholeProjectDecompiler
120123
// LOCAL moduleDefinition AS ModuleDefinition
@@ -237,8 +240,8 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
237240
SELF:WriteCode( output, options:DecompilerSettings, syntax, decompiler:TypeSystem)
238241
//
239242
RETURN NULL
240-
241-
243+
244+
242245
PRIVATE METHOD WriteCode(output AS ITextOutput, settings AS DecompilerSettings, syntaxTree AS SyntaxTree, typeSystem AS IDecompilerTypeSystem) AS VOID
243246
LOCAL visitor AS InsertParenthesesVisitor
244247
LOCAL writer1 AS TextTokenWriter
@@ -261,9 +264,9 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
261264
decoratedWriter := XSharpHighlightingTokenWriter{decoratedWriter, textOutput, xsSettings }
262265
ENDIF
263266
syntaxTree:AcceptVisitor(XSharpOutputVisitor{decoratedWriter, settings:CSharpFormattingOptions, typeSystem })
264-
265-
266-
267+
268+
269+
267270
PRIVATE METHOD CreateDecompiler(module AS PEFile, options AS DecompilationOptions ) AS CSharpDecompiler
268271
LOCAL decompiler AS CSharpDecompiler
269272
//
@@ -275,40 +278,40 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
275278
ENDDO
276279
// decompiler:AstTransforms:Add( EscapeInvalidIdentifiers{})
277280
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+
312315
PRIVATE STATIC METHOD CollectFieldsAndCtors(type AS ITypeDefinition , isStatic AS LOGIC ) AS List<EntityHandle>
313316
LOCAL list AS List<EntityHandle>
314317
LOCAL metadataToken AS EntityHandle
@@ -375,19 +378,19 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
375378
376379
377380
*/
378-
END CLASS
379-
380-
381-
381+
END CLASS
382+
383+
384+
382385
CLASS SelectCtorTransform IMPLEMENTS IAstTransform
383386
PRIVATE INITONLY ctor AS IMethod
384387
PRIVATE INITONLY removedSymbols := HashSet<ISymbol>{} AS HashSet<ISymbol>
385388

386389

387390
PUBLIC CONSTRUCTOR(ctor AS IMethod )
388391
SELF:ctor := ctor
389-
390-
392+
393+
391394
PUBLIC METHOD Run(rootNode AS AstNode , context AS TransformContext ) AS VOID
392395
LOCAL ctorDeclaration AS ConstructorDeclaration
393396
LOCAL currentAstNode AS AstNode
@@ -439,16 +442,16 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
439442
NEXT
440443

441444

442-
END CLASS
443-
444-
445+
END CLASS
446+
447+
445448
CLASS SelectFieldTransform IMPLEMENTS IAstTransform
446449
PRIVATE INITONLY fld AS IField
447450

448451
PUBLIC CONSTRUCTOR(fld AS IField )
449452
SELF:fld := fld
450-
451-
453+
454+
452455
PUBLIC METHOD Run(rootNode AS AstNode , context AS TransformContext ) AS VOID
453456
LOCAL currentAstNode AS AstNode
454457
LOCAL entityDeclaration1 AS EntityDeclaration
@@ -476,9 +479,9 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
476479
NEXT
477480

478481

479-
END CLASS
480-
481-
482+
END CLASS
483+
484+
482485
CLASS XSharpWholeProjectDecompiler INHERIT WholeProjectDecompiler
483486
PRIVATE INITONLY assembly AS LoadedAssembly
484487
PRIVATE INITONLY options AS DecompilationOptions
@@ -487,9 +490,9 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
487490
SUPER(options:DecompilerSettings, assembly:GetAssemblyResolver(), assembly:GetDebugInfoOrNull() )
488491
SELF:assembly := assembly
489492
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>>
493496
//
494497
FOREACH exportedValue AS IResourceFileHandler IN App.ExportProvider:GetExportedValues<IResourceFileHandler>()
495498
IF (exportedValue:CanHandle(fileName, SELF:options))
@@ -500,9 +503,69 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
500503
ENDIF
501504
NEXT
502505
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))
503566

504567

505568
END CLASS
506-
507-
569+
570+
508571
END NAMESPACE

ILSpy.XSharpLanguage/XSharpOutputVisitor.prg

+2-2
Original file line numberDiff line numberDiff line change
@@ -1000,8 +1000,8 @@ BEGIN NAMESPACE ILSpy.XSharpLanguage
10001000
VIRTUAL METHOD VisitContinueStatement(continueStatement AS ContinueStatement) AS VOID
10011001
//
10021002
SELF:StartNode(continueStatement)
1003-
SELF:WriteKeyword("continue", ContinueStatement.ContinueKeywordRole)
1004-
SELF:Semicolon()
1003+
SELF:WriteKeyword("Loop", ContinueStatement.ContinueKeywordRole)
1004+
SELF:NewLine()
10051005
SELF:EndNode(continueStatement)
10061006

10071007
VIRTUAL METHOD VisitCSharpTokenNode(cSharpTokenNode AS CSharpTokenNode) AS VOID

Readme.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ At that level, Create a ILSPY folder, and place there the ILSpy binaries.
44
After building, you will have a ILSpy.XSharpLanguage.Plugin.DLL in ILSpy.XSharpLanguage\bin\Debug or Release
55
Either run ILSpy in that folder, or copy/paste the file with the ILSpy binaries.
66

7-
This version has been built against V5.x
7+
The first version was been built against V5.x
88

99
This plugin is based on the source code found in ILSpy (https://github.com/icsharpcode/ILSpy) that provide CSharpLanguage.
1010
It has been used as base, and some modifications haven been made to support some XSharp construction.

0 commit comments

Comments
 (0)