diff --git a/ILSpy/App.axaml b/ILSpy/App.axaml
index c3a391f26..59fd1f3a5 100644
--- a/ILSpy/App.axaml
+++ b/ILSpy/App.axaml
@@ -5,6 +5,7 @@
xmlns:tree="using:ILSpy.AssemblyTree"
xmlns:search="using:ILSpy.Search"
xmlns:analyzers="using:ILSpy.Analyzers"
+ xmlns:textView="using:ILSpy.TextView"
xmlns:dockTheme="using:Dock.Avalonia.Themes.Simple"
xmlns:controls="using:ILSpy.Controls"
RequestedThemeVariant="Default">
@@ -35,12 +36,16 @@
+
+
+
+
diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index c877c05de..b555590ec 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -17,12 +17,21 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Collections.Generic;
using System.Composition;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
+using ICSharpCode.Decompiler.CSharp.Syntax;
+using ICSharpCode.Decompiler.CSharp.Transforms;
+using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
+using ICSharpCode.ILSpyX;
using ConversionFlags = ICSharpCode.Decompiler.Output.ConversionFlags;
@@ -60,5 +69,77 @@ namespace ILSpy.Languages
| ConversionFlags.ShowParameterModifiers;
return ambience.ConvertSymbol(entity);
}
+
+ public override void WriteCommentLine(ITextOutput output, string comment) => output.WriteLine("// " + comment);
+
+ public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(type.ParentModule?.MetadataFile != null);
+ DecompileEntities(type.ParentModule.MetadataFile, new[] { type.MetadataToken }, output, options);
+ }
+
+ public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(method.ParentModule?.MetadataFile != null);
+ DecompileEntities(method.ParentModule.MetadataFile, new[] { method.MetadataToken }, output, options);
+ }
+
+ public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(field.ParentModule?.MetadataFile != null);
+ DecompileEntities(field.ParentModule.MetadataFile, new[] { field.MetadataToken }, output, options);
+ }
+
+ public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(property.ParentModule?.MetadataFile != null);
+ DecompileEntities(property.ParentModule.MetadataFile, new[] { property.MetadataToken }, output, options);
+ }
+
+ public override void DecompileEvent(IEvent ev, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(ev.ParentModule?.MetadataFile != null);
+ DecompileEntities(ev.ParentModule.MetadataFile, new[] { ev.MetadataToken }, output, options);
+ }
+
+ public override void DecompileNamespace(string nameSpace, IEnumerable types, ITextOutput output, DecompilationOptions options)
+ {
+ var typesByModule = types.GroupBy(t => {
+ Debug.Assert(t.ParentModule?.MetadataFile != null);
+ return t.ParentModule.MetadataFile;
+ });
+ bool first = true;
+ foreach (var group in typesByModule)
+ {
+ if (!first)
+ output.WriteLine();
+ first = false;
+ DecompileEntities(group.Key, group.Select(t => t.MetadataToken), output, options);
+ }
+ }
+
+ void DecompileEntities(MetadataFile module, IEnumerable handles, ITextOutput output, DecompilationOptions options)
+ {
+ if (module == null)
+ {
+ WriteCommentLine(output, "(metadata file unavailable)");
+ return;
+ }
+ var resolver = module.GetAssemblyResolver(options.DecompilerSettings.AutoLoadAssemblyReferences);
+ var decompiler = new CSharpDecompiler(module, resolver, options.DecompilerSettings) {
+ CancellationToken = options.CancellationToken,
+ DebugInfoProvider = module.GetDebugInfoOrNull(),
+ };
+ SyntaxTree syntaxTree = decompiler.Decompile(handles);
+ WriteCode(output, options.DecompilerSettings, syntaxTree, decompiler.TypeSystem);
+ }
+
+ static void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
+ {
+ syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
+ output.IndentationString = settings.CSharpFormattingOptions.IndentationString;
+ TokenWriter tokenWriter = new TextTokenWriter(output, settings, typeSystem);
+ syntaxTree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, settings.CSharpFormattingOptions));
+ }
}
}
diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs
index d323bd0b6..784bc82d6 100644
--- a/ILSpy/Languages/Language.cs
+++ b/ILSpy/Languages/Language.cs
@@ -17,6 +17,8 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Collections.Generic;
+using System.Diagnostics;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
@@ -26,7 +28,7 @@ using ICSharpCode.Decompiler.TypeSystem;
namespace ILSpy.Languages
{
///
- /// Output language for tree-node labels and (eventually) decompiled views.
+ /// Output language for tree-node labels and decompiled views.
/// Subclasses override formatting for their target syntax. Implementations must be
/// thread-safe.
///
@@ -63,6 +65,52 @@ namespace ILSpy.Languages
return ambience.ConvertSymbol(entity);
}
+ ///
+ /// Writes as a single-line comment in this language's syntax.
+ ///
+ public virtual void WriteCommentLine(ITextOutput output, string comment)
+ {
+ output.WriteLine("// " + comment);
+ }
+
+ // Default Decompile* implementations write a stub comment so we always produce *something*
+ // for symbols whose language doesn't have a meaningful decompilation. Real languages
+ // (CSharpLanguage, eventually ILLanguage) override these.
+
+ public virtual void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
+ {
+ WriteCommentLine(output, TypeToString(type));
+ }
+
+ public virtual void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(method.DeclaringTypeDefinition != null);
+ WriteCommentLine(output, TypeToString(method.DeclaringTypeDefinition) + "." + method.Name);
+ }
+
+ public virtual void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(field.DeclaringTypeDefinition != null);
+ WriteCommentLine(output, TypeToString(field.DeclaringTypeDefinition) + "." + field.Name);
+ }
+
+ public virtual void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(property.DeclaringTypeDefinition != null);
+ WriteCommentLine(output, TypeToString(property.DeclaringTypeDefinition) + "." + property.Name);
+ }
+
+ public virtual void DecompileEvent(IEvent ev, ITextOutput output, DecompilationOptions options)
+ {
+ Debug.Assert(ev.DeclaringTypeDefinition != null);
+ WriteCommentLine(output, TypeToString(ev.DeclaringTypeDefinition) + "." + ev.Name);
+ }
+
+ public virtual void DecompileNamespace(string nameSpace, IEnumerable types, ITextOutput output, DecompilationOptions options)
+ {
+ WriteCommentLine(output, nameSpace);
+ }
+
public override string ToString() => Name;
}
}
diff --git a/ILSpy/TextView/Asm-Mode.xshd b/ILSpy/TextView/Asm-Mode.xshd
new file mode 100644
index 000000000..70dc222c4
--- /dev/null
+++ b/ILSpy/TextView/Asm-Mode.xshd
@@ -0,0 +1,1215 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ aaa
+ aad
+ aam
+ aas
+ adc
+ add
+ and
+ call
+ cbw
+ cdqe
+ clc
+ cld
+ cli
+ cmc
+ cmp
+ cmps
+ cmpsb
+ cmpsw
+ cwd
+ daa
+ das
+ dec
+ div
+ esc
+ hlt
+ idiv
+ imul
+ in
+ inc
+ int
+ into
+ iret
+ ja
+ jae
+ jb
+ jbe
+ jc
+ jcxz
+ je
+ jg
+ jge
+ jl
+ jle
+ jmp
+ jna
+ jnae
+ jnb
+ jnbe
+ jnc
+ jne
+ jng
+ jnge
+ jnl
+ jnle
+ jno
+ jnp
+ jns
+ jnz
+ jo
+ jp
+ jpe
+ jpo
+ js
+ jz
+ lahf
+ lds
+ lea
+ les
+ lods
+ lodsb
+ lodsw
+ loop
+ loope
+ loopew
+ loopne
+ loopnew
+ loopnz
+ loopnzw
+ loopw
+ loopz
+ loopzw
+ mov
+ movabs
+ movs
+ movsb
+ movsw
+ mul
+ neg
+ nop
+ not
+ or
+ out
+ pop
+ popf
+ push
+ pushf
+ rcl
+ rcr
+ ret
+ retf
+ retn
+ rol
+ ror
+ sahf
+ sal
+ sar
+ sbb
+ scas
+ scasb
+ scasw
+ shl
+ shr
+ stc
+ std
+ sti
+ stos
+ stosb
+ stosw
+ sub
+ test
+ wait
+ xchg
+ xlat
+ xlatb
+ xor
+ bound
+ enter
+ ins
+ insb
+ insw
+ leave
+ outs
+ outsb
+ outsw
+ popa
+ pusha
+ pushw
+ arpl
+ lar
+ lsl
+ sgdt
+ sidt
+ sldt
+ smsw
+ str
+ verr
+ verw
+ clts
+ lgdt
+ lidt
+ lldt
+ lmsw
+ ltr
+ bsf
+ bsr
+ bt
+ btc
+ btr
+ bts
+ cdq
+ cmpsd
+ cwde
+ insd
+ iretd
+ iretdf
+ iretf
+ jecxz
+ lfs
+ lgs
+ lodsd
+ loopd
+ looped
+ loopned
+ loopnzd
+ loopzd
+ lss
+ movsd
+ movsx
+ movsxd
+ movzx
+ outsd
+ popad
+ popfd
+ pushad
+ pushd
+ pushfd
+ scasd
+ seta
+ setae
+ setb
+ setbe
+ setc
+ sete
+ setg
+ setge
+ setl
+ setle
+ setna
+ setnae
+ setnb
+ setnbe
+ setnc
+ setne
+ setng
+ setnge
+ setnl
+ setnle
+ setno
+ setnp
+ setns
+ setnz
+ seto
+ setp
+ setpe
+ setpo
+ sets
+ setz
+ shld
+ shrd
+ stosd
+ bswap
+ cmpxchg
+ invd
+ invlpg
+ wbinvd
+ xadd
+ lock
+ rep
+ repe
+ repne
+ repnz
+ repz
+ cflush
+ cpuid
+ emms
+ femms
+ cmovo
+ cmovno
+ cmovb
+ cmovc
+ cmovnae
+ cmovae
+ cmovnb
+ cmovnc
+ cmove
+ cmovz
+ cmovne
+ cmovnz
+ cmovbe
+ cmovna
+ cmova
+ cmovnbe
+ cmovs
+ cmovns
+ cmovp
+ cmovpe
+ cmovnp
+ cmovpo
+ cmovl
+ cmovnge
+ cmovge
+ cmovnl
+ cmovle
+ cmovng
+ cmovg
+ cmovnle
+ cmpxchg486
+ cmpxchg8b
+ loadall
+ loadall286
+ ibts
+ icebp
+ int1
+ int3
+ int01
+ int03
+ iretw
+ popaw
+ popfw
+ pushaw
+ pushfw
+ rdmsr
+ rdpmc
+ rdshr
+ rdtsc
+ rsdc
+ rsldt
+ rsm
+ rsts
+ salc
+ smi
+ smint
+ smintold
+ svdc
+ svldt
+ svts
+ syscall
+ sysenter
+ sysexit
+ sysret
+ ud0
+ ud1
+ ud2
+ umov
+ xbts
+ wrmsr
+ wrshr
+
+
+ f2xm1
+ fabs
+ fadd
+ faddp
+ fbld
+ fbstp
+ fchs
+ fclex
+ fcom
+ fcomp
+ fcompp
+ fdecstp
+ fdisi
+ fdiv
+ fdivp
+ fdivr
+ fdivrp
+ feni
+ ffree
+ fiadd
+ ficom
+ ficomp
+ fidiv
+ fidivr
+ fild
+ fimul
+ fincstp
+ finit
+ fist
+ fistp
+ fisub
+ fisubr
+ fld
+ fld1
+ fldcw
+ fldenv
+ fldenvw
+ fldl2e
+ fldl2t
+ fldlg2
+ fldln2
+ fldpi
+ fldz
+ fmul
+ fmulp
+ fnclex
+ fndisi
+ fneni
+ fninit
+ fnop
+ fnsave
+ fnsavew
+ fnstcw
+ fnstenv
+ fnstenvw
+ fnstsw
+ fpatan
+ fprem
+ fptan
+ frndint
+ frstor
+ frstorw
+ fsave
+ fsavew
+ fscale
+ fsqrt
+ fst
+ fstcw
+ fstenv
+ fstenvw
+ fstp
+ fstsw
+ fsub
+ fsubp
+ fsubr
+ fsubrp
+ ftst
+ fwait
+ fxam
+ fxch
+ fxtract
+ fyl2x
+ fyl2xp1
+ fsetpm
+ fcos
+ fldenvd
+ fnsaved
+ fnstenvd
+ fprem1
+ frstord
+ fsaved
+ fsin
+ fsincos
+ fstenvd
+ fucom
+ fucomp
+ fucompp
+ fcomi
+ fcomip
+ ffreep
+ fcmovb
+ fcmove
+ fcmovbe
+ fcmovu
+ fcmovnb
+ fcmovne
+ fcmovnbe
+ fcmovnu
+
+
+ ah
+ al
+ ax
+ bh
+ bl
+ bp
+ bx
+ ch
+ cl
+ cr0
+ cr2
+ cr3
+ cr4
+ cs
+ cx
+ dh
+ di
+ dl
+ dr0
+ dr1
+ dr2
+ dr3
+ dr6
+ dr7
+ ds
+ dx
+ eax
+ ebp
+ ebx
+ ecx
+ edi
+ edx
+ es
+ esi
+ esp
+ fs
+ gs
+ rax
+ rbx
+ rcx
+ rdx
+ rdi
+ rsi
+ rbp
+ rsp
+ r8
+ r9
+ r10
+ r11
+ r12
+ r13
+ r14
+ r15
+ r8d
+ r9d
+ r10d
+ r11d
+ r12d
+ r13d
+ r14d
+ r15d
+ r8w
+ r9w
+ r10w
+ r11w
+ r12w
+ r13w
+ r14w
+ r15w
+ r8b
+ r9b
+ r10b
+ r11b
+ r12b
+ r13b
+ r14b
+ r15b
+ si
+ sp
+ ss
+ st
+ tr3
+ tr4
+ tr5
+ tr6
+ tr7
+ st0
+ st1
+ st2
+ st3
+ st4
+ st5
+ st6
+ st7
+ mm0
+ mm1
+ mm2
+ mm3
+ mm4
+ mm5
+ mm6
+ mm7
+ xmm0
+ xmm1
+ xmm2
+ xmm3
+ xmm4
+ xmm5
+ xmm6
+ xmm7
+ xmm8
+ xmm9
+ xmm10
+ xmm11
+ xmm12
+ xmm13
+ xmm14
+ xmm15
+
+
+ .186
+ .286
+ .286c
+ .286p
+ .287
+ .386
+ .386c
+ .386p
+ .387
+ .486
+ .486p
+ .8086
+ .8087
+ .alpha
+ .break
+ .code
+ .const
+ .continue
+ .cref
+ .data
+ .data?
+ .dosseg
+ .else
+ .elseif
+ .endif
+ .endw
+ .err
+ .err1
+ .err2
+ .errb
+ .errdef
+ .errdif
+ .errdifi
+ .erre
+ .erridn
+ .erridni
+ .errnb
+ .errndef
+ .errnz
+ .exit
+ .fardata
+ .fardata?
+ .if
+ .lall
+ .lfcond
+ .list
+ .listall
+ .listif
+ .listmacro
+ .listmacroall
+ .model
+ .no87
+ .nocref
+ .nolist
+ .nolistif
+ .nolistmacro
+ .radix
+ .repeat
+ .sall
+ .seq
+ .sfcond
+ .stack
+ .startup
+ .tfcond
+ .type
+ .until
+ .untilcxz
+ .while
+ .xall
+ .xcref
+ .xlist
+ alias
+ align
+ assume
+ catstr
+ comm
+ comment
+ db
+ dd
+ df
+ dosseg
+ dq
+ dt
+ dup
+ dw
+ echo
+ else
+ elseif
+ elseif1
+ elseif2
+ elseifb
+ elseifdef
+ elseifdif
+ elseifdifi
+ elseife
+ elseifidn
+ elseifidni
+ elseifnb
+ elseifndef
+ end
+ endif
+ endm
+ endp
+ ends
+ eq
+ equ
+ even
+ exitm
+ extern
+ externdef
+ extrn
+ for
+ forc
+ ge
+ goto
+ group
+ gt
+ high
+ highword
+ if
+ if1
+ if2
+ ifb
+ ifdef
+ ifdif
+ ifdifi
+ ife
+ ifidn
+ ifidni
+ ifnb
+ ifndef
+ include
+ includelib
+ instr
+ invoke
+ irp
+ irpc
+ label
+ le
+ length
+ lengthof
+ local
+ low
+ lowword
+ lroffset
+ lt
+ macro
+ mask
+ mod
+ .msfloat
+ name
+ ne
+ offset
+ opattr
+ option
+ org
+ %out
+ page
+ popcontext
+ proc
+ proto
+ ptr
+ public
+ purge
+ pushcontext
+ record
+ repeat
+ rept
+ seg
+ segment
+ short
+ size
+ sizeof
+ sizestr
+ struc
+ struct
+ substr
+ subtitle
+ subttl
+ textequ
+ this
+ title
+ type
+ typedef
+ union
+ while
+ width
+ resb
+ resw
+ resd
+ resq
+ rest
+ incbin
+ times
+ %define
+ %idefine
+ %xdefine
+ %xidefine
+ %undef
+ %assign
+ %iassign
+ %strlen
+ %substr
+ %macro
+ %imacro
+ %endmacro
+ %rotate
+ %if
+ %elif
+ %else
+ %endif
+ %ifdef
+ %ifndef
+ %elifdef
+ %elifndef
+ %ifmacro
+ %ifnmacro
+ %elifmacro
+ %elifnmacro
+ %ifctk
+ %ifnctk
+ %elifctk
+ %elifnctk
+ %ifidn
+ %ifnidn
+ %elifidn
+ %elifnidn
+ %ifidni
+ %ifnidni
+ %elifidni
+ %elifnidni
+ %ifid
+ %ifnid
+ %elifid
+ %elifnid
+ %ifstr
+ %ifnstr
+ %elifstr
+ %elifnstr
+ %ifnum
+ %ifnnum
+ %elifnum
+ %elifnnum
+ %error
+ %rep
+ %endrep
+ %exitrep
+ %include
+ %push
+ %pop
+ %repl
+ endstruc
+ istruc
+ at
+ iend
+ alignb
+ %arg
+ %stacksize
+ %local
+ %line
+ bits
+ use16
+ use32
+ section
+ absolute
+ global
+ common
+ cpu
+ import
+ export
+
+
+ $
+ ?
+ @b
+ @f
+ addr
+ basic
+ byte
+ c
+ carry?
+ dword
+ far
+ far16
+ fortran
+ fword
+ near
+ near16
+ overflow?
+ parity?
+ pascal
+ qword
+ real4
+ real8
+ real10
+ sbyte
+ sdword
+ sign?
+ stdcall
+ sword
+ syscall
+ tbyte
+ vararg
+ word
+ zero?
+ flat
+ near32
+ far32
+ abs
+ all
+ assumes
+ at
+ casemap
+ common
+ compact
+ cpu
+ dotname
+ emulator
+ epilogue
+ error
+ export
+ expr16
+ expr32
+ farstack
+ forceframe
+ huge
+ language
+ large
+ listing
+ ljmp
+ loadds
+ m510
+ medium
+ memory
+ nearstack
+ nodotname
+ noemulator
+ nokeyword
+ noljmp
+ nom510
+ none
+ nonunique
+ nooldmacros
+ nooldstructs
+ noreadonly
+ noscoped
+ nosignextend
+ nothing
+ notpublic
+ oldmacros
+ oldstructs
+ os_dos
+ para
+ private
+ prologue
+ radix
+ readonly
+ req
+ scoped
+ setif2
+ smallstack
+ tiny
+ use16
+ use32
+ uses
+ a16
+ a32
+ o16
+ o32
+ nosplit
+ $$
+ seq
+ wrt
+ small
+ .text
+ .data
+ .bss
+ %0
+ %1
+ %2
+ %3
+ %4
+ %5
+ %6
+ %7
+ %8
+ %9
+
+
+ addpd
+ addps
+ addsd
+ addss
+ andpd
+ andps
+ andnpd
+ andnps
+ cmpeqpd
+ cmpltpd
+ cmplepd
+ cmpunordpd
+ cmpnepd
+ cmpnltpd
+ cmpnlepd
+ cmpordpd
+ cmpeqps
+ cmpltps
+ cmpleps
+ cmpunordps
+ cmpneps
+ cmpnltps
+ cmpnleps
+ cmpordps
+ cmpeqsd
+ cmpltsd
+ cmplesd
+ cmpunordsd
+ cmpnesd
+ cmpnltsd
+ cmpnlesd
+ cmpordsd
+ cmpeqss
+ cmpltss
+ cmpless
+ cmpunordss
+ cmpness
+ cmpnltss
+ cmpnless
+ cmpordss
+ comisd
+ comiss
+ cvtdq2pd
+ cvtdq2ps
+ cvtpd2dq
+ cvtpd2pi
+ cvtpd2ps
+ cvtpi2pd
+ cvtpi2ps
+ cvtps2dq
+ cvtps2pd
+ cvtps2pi
+ cvtss2sd
+ cvtss2si
+ cvtsd2si
+ cvtsd2ss
+ cvtsi2sd
+ cvtsi2ss
+ cvttpd2dq
+ cvttpd2pi
+ cvttps2dq
+ cvttps2pi
+ cvttsd2si
+ cvttss2si
+ divpd
+ divps
+ divsd
+ divss
+ fxrstor
+ fxsave
+ ldmxscr
+ lfence
+ mfence
+ maskmovdqu
+ maskmovdq
+ maxpd
+ maxps
+ paxsd
+ maxss
+ minpd
+ minps
+ minsd
+ minss
+ movapd
+ movaps
+ movdq2q
+ movdqa
+ movdqu
+ movhlps
+ movhpd
+ movhps
+ movd
+ movq
+ movlhps
+ movlpd
+ movlps
+ movmskpd
+ movmskps
+ movntdq
+ movnti
+ movntpd
+ movntps
+ movntq
+ movq2dq
+ movsd
+ movss
+ movupd
+ movups
+ mulpd
+ mulps
+ mulsd
+ mulss
+ orpd
+ orps
+ packssdw
+ packsswb
+ packuswb
+ paddb
+ paddsb
+ paddw
+ paddsw
+ paddd
+ paddsiw
+ paddq
+ paddusb
+ paddusw
+ pand
+ pandn
+ pause
+ paveb
+ pavgb
+ pavgw
+ pavgusb
+ pdistib
+ pextrw
+ pcmpeqb
+ pcmpeqw
+ pcmpeqd
+ pcmpgtb
+ pcmpgtw
+ pcmpgtd
+ pf2id
+ pf2iw
+ pfacc
+ pfadd
+ pfcmpeq
+ pfcmpge
+ pfcmpgt
+ pfmax
+ pfmin
+ pfmul
+ pmachriw
+ pmaddwd
+ pmagw
+ pmaxsw
+ pmaxub
+ pminsw
+ pminub
+ pmovmskb
+ pmulhrwc
+ pmulhriw
+ pmulhrwa
+ pmulhuw
+ pmulhw
+ pmullw
+ pmuludq
+ pmvzb
+ pmvnzb
+ pmvlzb
+ pmvgezb
+ pfnacc
+ pfpnacc
+ por
+ prefetch
+ prefetchw
+ prefetchnta
+ prefetcht0
+ prefetcht1
+ prefetcht2
+ pfrcp
+ pfrcpit1
+ pfrcpit2
+ pfrsqit1
+ pfrsqrt
+ pfsub
+ pfsubr
+ pi2fd
+ pinsrw
+ psadbw
+ pshufd
+ pshufhw
+ pshuflw
+ pshufw
+ psllw
+ pslld
+ psllq
+ pslldq
+ psraw
+ psrad
+ psrlw
+ psrld
+ psrlq
+ psrldq
+ psubb
+ psubw
+ psubd
+ psubq
+ psubsb
+ psubsw
+ psubusb
+ psubusw
+ psubsiw
+ pswapd
+ punpckhbw
+ punpckhwd
+ punpckhdq
+ punpckhqdq
+ punpcklbw
+ punpcklwd
+ punpckldq
+ punpcklqdq
+ pxor
+ rcpps
+ rcpss
+ rsqrtps
+ rsqrtss
+ sfence
+ shufpd
+ shufps
+ sqrtpd
+ sqrtps
+ sqrtsd
+ sqrtss
+ stmxcsr
+ subpd
+ subps
+ subsd
+ subss
+ ucomisd
+ ucomiss
+ unpckhpd
+ unpckhps
+ unpcklpd
+ unpcklps
+ xorpd
+ xorps
+
+
+ ;
+
+
+ ^ \s* [0-9A-F]+ \s+ [0-9A-F]+
+
+
+ \b(0[xXhH])?[0-9a-fA-F_`]+[h]? # hex number
+ |
+ ( \b\d+(\.[0-9]+)? #number with optional floating point
+ | \.[0-9]+ #or just starting with floating point
+ )
+ ([eE][+-]?[0-9]+)? # optional exponent
+
+
+
+
+ TODO
+ FIXME
+
+
+ HACK
+ UNDONE
+
+
+
\ No newline at end of file
diff --git a/ILSpy/TextView/AvaloniaEditTextOutput.cs b/ILSpy/TextView/AvaloniaEditTextOutput.cs
new file mode 100644
index 000000000..8b0f34881
--- /dev/null
+++ b/ILSpy/TextView/AvaloniaEditTextOutput.cs
@@ -0,0 +1,106 @@
+// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System.Reflection.Metadata;
+using System.Text;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Disassembler;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.Decompiler.TypeSystem;
+
+namespace ILSpy.TextView
+{
+ ///
+ /// Phase-1 for the Avalonia text view: just accumulates text into a
+ /// with the indentation contract the decompiler expects. Reference
+ /// markers, fold ranges, and inline UI elements are intentionally dropped — those will land
+ /// when we add hyperlinks and folding support.
+ ///
+ sealed class AvaloniaEditTextOutput : ITextOutput
+ {
+ readonly StringBuilder builder = new();
+ int indent;
+ bool needsIndent;
+
+ public string IndentationString { get; set; } = "\t";
+
+ public int TextLength => builder.Length;
+
+ public string GetText() => builder.ToString();
+
+ public void Indent() => indent++;
+
+ public void Unindent()
+ {
+ if (indent > 0)
+ indent--;
+ }
+
+ void WriteIndentIfNeeded()
+ {
+ if (!needsIndent)
+ return;
+ needsIndent = false;
+ for (int i = 0; i < indent; i++)
+ builder.Append(IndentationString);
+ }
+
+ public void Write(char ch)
+ {
+ WriteIndentIfNeeded();
+ builder.Append(ch);
+ }
+
+ public void Write(string text)
+ {
+ WriteIndentIfNeeded();
+ builder.Append(text);
+ }
+
+ public void WriteLine()
+ {
+ builder.Append('\n');
+ needsIndent = true;
+ }
+
+ public void WriteReference(OpCodeInfo opCode, bool omitSuffix = false)
+ {
+ Write(omitSuffix ? opCode.Name.TrimEnd('.') : opCode.Name);
+ }
+
+ public void WriteReference(MetadataFile metadata, Handle handle, string text, string protocol = "decompile", bool isDefinition = false)
+ => Write(text);
+
+ public void WriteReference(IType type, string text, bool isDefinition = false) => Write(text);
+
+ public void WriteReference(IMember member, string text, bool isDefinition = false) => Write(text);
+
+ public void WriteLocalReference(string text, object reference, bool isDefinition = false) => Write(text);
+
+ public void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false, bool isDefinition = false)
+ {
+ // Folding support arrives in a later phase.
+ }
+
+ public void MarkFoldEnd()
+ {
+ // Folding support arrives in a later phase.
+ }
+ }
+}
diff --git a/ILSpy/TextView/CSharp-Mode.xshd b/ILSpy/TextView/CSharp-Mode.xshd
new file mode 100644
index 000000000..e3f502de9
--- /dev/null
+++ b/ILSpy/TextView/CSharp-Mode.xshd
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TODO
+ FIXME
+
+
+ HACK
+ UNDONE
+
+
+
+
+
+
+ \#
+
+
+
+ (define|undef|if|elif|else|endif|line)\b
+
+
+
+ //
+
+
+
+
+
+ (region|endregion|error|warning|pragma)\b
+
+
+
+
+
+
+ ///(?!/)
+
+
+
+
+
+
+
+ //
+
+
+
+ /\*
+ \*/
+
+
+
+ "
+ "
+
+
+
+
+
+
+
+ '
+ '
+
+
+
+
+
+
+
+ @"
+ "
+
+
+
+
+
+
+
+ \$"
+ "
+
+
+
+
+
+
+
+
+
+
+
+ \b0[xX][0-9a-fA-F]+ # hex number
+ |
+ ( \b\d+(\.[0-9]+)? #number with optional floating point
+ | \.[0-9]+ #or just starting with floating point
+ )
+ ([eE][+-]?[0-9]+)? # optional exponent
+
+
+
diff --git a/ILSpy/TextView/DecompilerTabPageModel.cs b/ILSpy/TextView/DecompilerTabPageModel.cs
new file mode 100644
index 000000000..60037a059
--- /dev/null
+++ b/ILSpy/TextView/DecompilerTabPageModel.cs
@@ -0,0 +1,125 @@
+// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Avalonia.Threading;
+
+using CommunityToolkit.Mvvm.ComponentModel;
+
+using ICSharpCode.Decompiler;
+
+using ILSpy.Languages;
+using ILSpy.TreeNodes;
+using ILSpy.ViewModels;
+
+namespace ILSpy.TextView
+{
+ ///
+ /// A document tab that hosts decompiled output for a single tree node. Re-decompiles when
+ /// changes; previous in-flight decompilations are cancelled so a
+ /// rapid tree-selection sweep doesn't pile up background work.
+ ///
+ public sealed partial class DecompilerTabPageModel : TabPageModel
+ {
+ CancellationTokenSource? activeCts;
+
+ [ObservableProperty]
+ private string text = string.Empty;
+
+ ///
+ /// File extension driving syntax highlighting (e.g. ".cs"). Updated alongside .
+ ///
+ [ObservableProperty]
+ private string syntaxExtension = ".cs";
+
+ ILSpyTreeNode? currentNode;
+
+ public ILSpyTreeNode? CurrentNode {
+ get => currentNode;
+ set {
+ if (currentNode == value)
+ return;
+ currentNode = value;
+ _ = DecompileAsync();
+ }
+ }
+
+ public DecompilerTabPageModel()
+ {
+ Title = "Empty";
+ }
+
+ public Language Language { get; set; } = null!;
+
+ async Task DecompileAsync()
+ {
+ activeCts?.Cancel();
+ var cts = activeCts = new CancellationTokenSource();
+ var node = currentNode;
+ var language = Language;
+ if (node == null || language == null)
+ {
+ Text = string.Empty;
+ return;
+ }
+
+ Title = node.Text?.ToString() ?? "(unnamed)";
+ Text = "Decompiling…";
+ SyntaxExtension = language.FileExtension;
+
+ try
+ {
+ var (output, _) = await Task.Run(() => {
+ var output = new AvaloniaEditTextOutput();
+ var options = new DecompilationOptions { CancellationToken = cts.Token };
+ try
+ {
+ node.Decompile(language, output, options);
+ }
+ catch (OperationCanceledException)
+ {
+ // expected on cancel — just return whatever we got
+ }
+ catch (Exception ex)
+ {
+ output.WriteLine();
+ output.WriteLine("/* Decompilation failed:");
+ output.WriteLine(ex.ToString());
+ output.WriteLine("*/");
+ }
+ return (output, cts.Token);
+ }, cts.Token).ConfigureAwait(true);
+
+ if (cts.Token.IsCancellationRequested)
+ return;
+
+ var rendered = output.GetText();
+ await Dispatcher.UIThread.InvokeAsync(() => {
+ Text = rendered;
+ });
+ }
+ catch (OperationCanceledException)
+ {
+ // stale request — drop silently
+ }
+ }
+ }
+}
diff --git a/ILSpy/TextView/DecompilerTextView.axaml b/ILSpy/TextView/DecompilerTextView.axaml
new file mode 100644
index 000000000..987836bd6
--- /dev/null
+++ b/ILSpy/TextView/DecompilerTextView.axaml
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/ILSpy/TextView/DecompilerTextView.axaml.cs b/ILSpy/TextView/DecompilerTextView.axaml.cs
new file mode 100644
index 000000000..369d8c68a
--- /dev/null
+++ b/ILSpy/TextView/DecompilerTextView.axaml.cs
@@ -0,0 +1,59 @@
+// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System.ComponentModel;
+
+using Avalonia.Controls;
+
+namespace ILSpy.TextView
+{
+ public partial class DecompilerTextView : UserControl
+ {
+ public DecompilerTextView()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnDataContextChanged(System.EventArgs e)
+ {
+ base.OnDataContextChanged(e);
+ if (DataContext is DecompilerTabPageModel model)
+ {
+ model.PropertyChanged += OnModelPropertyChanged;
+ ApplyDocument(model);
+ }
+ }
+
+ void OnModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (sender is DecompilerTabPageModel model
+ && (e.PropertyName == nameof(DecompilerTabPageModel.Text)
+ || e.PropertyName == nameof(DecompilerTabPageModel.SyntaxExtension)))
+ {
+ ApplyDocument(model);
+ }
+ }
+
+ void ApplyDocument(DecompilerTabPageModel model)
+ {
+ Editor.SyntaxHighlighting = HighlightingService.GetByExtension(model.SyntaxExtension);
+ Editor.Document.Text = model.Text;
+ Editor.ScrollToHome();
+ }
+ }
+}
diff --git a/ILSpy/TextView/HighlightingService.cs b/ILSpy/TextView/HighlightingService.cs
new file mode 100644
index 000000000..cfcf4a3a4
--- /dev/null
+++ b/ILSpy/TextView/HighlightingService.cs
@@ -0,0 +1,79 @@
+// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.IO;
+using System.Xml;
+
+using AvaloniaEdit.Highlighting;
+using AvaloniaEdit.Highlighting.Xshd;
+
+namespace ILSpy.TextView
+{
+ ///
+ /// Loads our XSHD highlighting definitions (CSharp / IL / Asm / XML) from embedded resources
+ /// once and registers them with AvaloniaEdit's . Lookup by
+ /// file extension (".cs" / ".il" / ".asm" / ".xml") matches what
+ /// returns.
+ ///
+ static class HighlightingService
+ {
+ static bool registered;
+ static readonly object gate = new();
+
+ // Embedded resource names follow the csproj RootNamespace ("ICSharpCode.ILSpy"),
+ // not the file's C# namespace ("ILSpy").
+ const string ResourcePrefix = "ICSharpCode.ILSpy.TextView.";
+
+ public static void EnsureRegistered()
+ {
+ if (registered)
+ return;
+ lock (gate)
+ {
+ if (registered)
+ return;
+ Register("C#", new[] { ".cs" }, "CSharp-Mode.xshd");
+ Register("IL", new[] { ".il" }, "ILAsm-Mode.xshd");
+ Register("Asm", new[] { ".asm" }, "Asm-Mode.xshd");
+ Register("XML", new[] { ".xml", ".xaml" }, "XML-Mode.xshd");
+ registered = true;
+ }
+ }
+
+ public static IHighlightingDefinition? GetByExtension(string fileExtension)
+ {
+ EnsureRegistered();
+ return HighlightingManager.Instance.GetDefinitionByExtension(fileExtension);
+ }
+
+ static void Register(string name, string[] extensions, string resourceName)
+ {
+ HighlightingManager.Instance.RegisterHighlighting(name, extensions, () => Load(resourceName));
+ }
+
+ static IHighlightingDefinition Load(string resourceName)
+ {
+ using var stream = typeof(HighlightingService).Assembly
+ .GetManifestResourceStream(ResourcePrefix + resourceName)
+ ?? throw new InvalidOperationException($"Highlighting resource not found: {resourceName}");
+ using var reader = XmlReader.Create(stream);
+ return HighlightingLoader.Load(reader, HighlightingManager.Instance);
+ }
+ }
+}
diff --git a/ILSpy/TextView/ILAsm-Mode.xshd b/ILSpy/TextView/ILAsm-Mode.xshd
new file mode 100644
index 000000000..e376f9410
--- /dev/null
+++ b/ILSpy/TextView/ILAsm-Mode.xshd
@@ -0,0 +1,540 @@
+
+
+
+
+
+
+
+
+
+
+
+ nop
+ break
+ ldarg.0
+ ldarg.1
+ ldarg.2
+ ldarg.3
+ ldloc.0
+ ldloc.1
+ ldloc.2
+ ldloc.3
+ stloc.0
+ stloc.1
+ stloc.2
+ stloc.3
+ ldarg.s
+ ldarga.s
+ starg.s
+ ldloc.s
+ ldloca.s
+ stloc.s
+ ldnull
+ ldc.i4.m1
+ ldc.i4.0
+ ldc.i4.1
+ ldc.i4.2
+ ldc.i4.3
+ ldc.i4.4
+ ldc.i4.5
+ ldc.i4.6
+ ldc.i4.7
+ ldc.i4.8
+ ldc.i4.s
+ ldc.i4
+ ldc.i8
+ ldc.r4
+ ldc.r8
+ dup
+ pop
+ jmp
+ call
+ calli
+ ret
+ br.s
+ brfalse.s
+ brtrue.s
+ beq.s
+ bge.s
+ bgt.s
+ ble.s
+ blt.s
+ bne.un.s
+ bge.un.s
+ bgt.un.s
+ ble.un.s
+ blt.un.s
+ br
+ brfalse
+ brtrue
+ beq
+ bge
+ bgt
+ ble
+ blt
+ bne.un
+ bge.un
+ bgt.un
+ ble.un
+ blt.un
+ switch
+ ldind.i1
+ ldind.u1
+ ldind.i2
+ ldind.u2
+ ldind.i4
+ ldind.u4
+ ldind.i8
+ ldind.i
+ ldind.r4
+ ldind.r8
+ ldind.ref
+ stind.ref
+ stind.i1
+ stind.i2
+ stind.i4
+ stind.i8
+ stind.r4
+ stind.r8
+ add
+ sub
+ mul
+ div
+ div.un
+ rem
+ rem.un
+ and
+ or
+ xor
+ shl
+ shr
+ shr.un
+ neg
+ not
+ conv.i1
+ conv.i2
+ conv.i4
+ conv.i8
+ conv.r4
+ conv.r8
+ conv.u4
+ conv.u8
+ callvirt
+ cpobj
+ ldobj
+ ldstr
+ newobj
+ castclass
+ isinst
+ conv.r.un
+ unbox
+ throw
+ ldfld
+ ldflda
+ stfld
+ ldsfld
+ ldsflda
+ stsfld
+ stobj
+ conv.ovf.i1.un
+ conv.ovf.i2.un
+ conv.ovf.i4.un
+ conv.ovf.i8.un
+ conv.ovf.u1.un
+ conv.ovf.u2.un
+ conv.ovf.u4.un
+ conv.ovf.u8.un
+ conv.ovf.i.un
+ conv.ovf.u.un
+ box
+ newarr
+ ldlen
+ ldelema
+ ldelem
+ ldelem.i1
+ ldelem.u1
+ ldelem.i2
+ ldelem.u2
+ ldelem.i4
+ ldelem.u4
+ ldelem.i8
+ ldelem.i
+ ldelem.r4
+ ldelem.r8
+ ldelem.ref
+ stelem
+ stelem.i
+ stelem.i1
+ stelem.i2
+ stelem.i4
+ stelem.i8
+ stelem.r4
+ stelem.r8
+ stelem.ref
+ conv.ovf.i1
+ conv.ovf.u1
+ conv.ovf.i2
+ conv.ovf.u2
+ conv.ovf.i4
+ conv.ovf.u4
+ conv.ovf.i8
+ conv.ovf.u8
+ refanyval
+ ckfinite
+ mkrefany
+ ldtoken
+ conv.u2
+ conv.u1
+ conv.i
+ conv.ovf.i
+ conv.ovf.u
+ add.ovf
+ add.ovf.un
+ mul.ovf
+ mul.ovf.un
+ sub.ovf
+ sub.ovf.un
+ endfinally
+ leave
+ leave.s
+ stind.i
+ conv.u
+ prefix7
+ prefix6
+ prefix5
+ prefix4
+ prefix3
+ prefix2
+ prefix1
+ prefixref
+ arglist
+ ceq
+ cgt
+ cgt.un
+ clt
+ clt.un
+ ldftn
+ ldvirtftn
+ ldarg
+ ldarga
+ starg
+ ldloc
+ ldloca
+ stloc
+ localloc
+ endfilter
+ unaligned.
+ volatile.
+ tail.
+ initobj
+ cpblk
+ initblk
+ rethrow
+ sizeof
+ refanytype
+ illegal
+ endmac
+ brnull
+ brnull.s
+ brzero
+ brzero.s
+ brinst
+ brinst.s
+ ldind.u8
+ ldelem.u8
+ ldc.i4.M1
+ endfault
+
+
+ void
+ bool
+ char
+ wchar
+ int
+ int8
+ int16
+ int32
+ int64
+ uint8
+ uint16
+ uint32
+ uint64
+ float
+ float32
+ float64
+ refany
+ typedref
+ object
+ string
+ native
+ unsigned
+ value
+ valuetype
+ class
+ const
+ vararg
+ default
+ stdcall
+ thiscall
+ fastcall
+ unmanaged
+ not_in_gc_heap
+ beforefieldinit
+ instance
+ filter
+ catch
+ static
+ public
+ private
+ synchronized
+ interface
+ extends
+ implements
+ handler
+ finally
+ fault
+ to
+ abstract
+ auto
+ sequential
+ explicit
+ wrapper
+ ansi
+ unicode
+ autochar
+ import
+ enum
+ virtual
+ notremotable
+ special
+ il
+ cil
+ optil
+ managed
+ preservesig
+ runtime
+ method
+ field
+ bytearray
+ final
+ sealed
+ specialname
+ family
+ assembly
+ famandassem
+ famorassem
+ privatescope
+ nested
+ hidebysig
+ newslot
+ rtspecialname
+ pinvokeimpl
+ unmanagedexp
+ reqsecobj
+ .ctor
+ .cctor
+ initonly
+ literal
+ notserialized
+ forwardref
+ internalcall
+ noinlining
+ aggressiveinlining
+ nomangle
+ lasterr
+ winapi
+ cdecl
+ stdcall
+ thiscall
+ fastcall
+ as
+ pinned
+ modreq
+ modopt
+ serializable
+ at
+ tls
+ true
+ false
+ strict
+ type
+
+
+ .class
+ .namespace
+ .method
+ .field
+ .emitbyte
+ .try
+ .maxstack
+ .locals
+ .entrypoint
+ .zeroinit
+ .pdirect
+ .data
+ .event
+ .addon
+ .removeon
+ .fire
+ .other
+ protected
+ .property
+ .set
+ .get
+ default
+ .import
+ .permission
+ .permissionset
+ .line
+ .language
+ .interfaceimpl
+ #line
+
+
+ request
+ demand
+ assert
+ deny
+ permitonly
+ linkcheck
+ inheritcheck
+ reqmin
+ reqopt
+ reqrefuse
+ prejitgrant
+ prejitdeny
+ noncasdemand
+ noncaslinkdemand
+ noncasinheritance
+
+
+
+ .custom
+
+ init
+
+ .size
+ .pack
+
+ .file
+ nometadata
+ .hash
+ .assembly
+ implicitcom
+ noappdomain
+ noprocess
+ nomachine
+ .publickey
+ .publickeytoken
+ algorithm
+ .ver
+ .locale
+ extern
+ .export
+ .manifestres
+ .mresource
+ .localized
+
+
+ .module
+ marshal
+ custom
+ sysstring
+ fixed
+ variant
+ currency
+ syschar
+ decimal
+ date
+ bstr
+ tbstr
+ lpstr
+ lpwstr
+ lptstr
+ objectref
+ iunknown
+ idispatch
+ struct
+ safearray
+ byvalstr
+ lpvoid
+ any
+ array
+ lpstruct
+
+
+ .vtfixup
+ fromunmanaged
+ callmostderived
+ .vtentry
+
+
+ in
+ out
+ opt
+ lcid
+ retval
+ .param
+
+
+ .override
+ with
+
+
+ null
+ error
+ hresult
+ carray
+ userdefined
+ record
+ filetime
+ blob
+ stream
+ storage
+ streamed_object
+ stored_object
+ blob_object
+ cf
+ clsid
+ vector
+
+
+ nullref
+
+
+ .subsystem
+ .corflags
+ .stackreserve
+ alignment
+ .imagebase
+
+
+ //
+
+
+ /\*
+ \*/
+
+
+ "
+ "
+
+
+ '
+ '
+
+
+ ^ \s* \w+ :
+
+
+
+
+ TODO
+ FIXME
+
+
+ HACK
+ UNDONE
+
+
+
\ No newline at end of file
diff --git a/ILSpy/TextView/XML-Mode.xshd b/ILSpy/TextView/XML-Mode.xshd
new file mode 100644
index 000000000..8f0bdef76
--- /dev/null
+++ b/ILSpy/TextView/XML-Mode.xshd
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <!--
+ -->
+
+
+ <!\[CDATA\[
+ ]]>
+
+
+ <!DOCTYPE
+ >
+
+
+ <\?
+ \?>
+
+
+ <
+ >
+
+
+
+ "
+ "|(?=<)
+
+
+ '
+ '|(?=<)
+
+ [\d\w_\-\.]+(?=(\s*=))
+ =
+
+
+
+
+
+
+
+ &
+ [\w\d\#]+
+ ;
+
+
+
+ &
+ [\w\d\#]*
+ #missing ;
+
+
+
\ No newline at end of file
diff --git a/ILSpy/TreeNodes/EventTreeNode.cs b/ILSpy/TreeNodes/EventTreeNode.cs
index 3bd9386c7..d6913fc89 100644
--- a/ILSpy/TreeNodes/EventTreeNode.cs
+++ b/ILSpy/TreeNodes/EventTreeNode.cs
@@ -18,9 +18,12 @@
using System;
+using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
+using ILSpy.Languages;
+
namespace ILSpy.TreeNodes
{
sealed class EventTreeNode : ILSpyTreeNode
@@ -37,6 +40,9 @@ namespace ILSpy.TreeNodes
Images.Images.GetOverlay(EventDefinition.Accessibility), EventDefinition.IsStatic);
public override bool ShowExpander => false;
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ => language.DecompileEvent(EventDefinition, output, options);
+
public override string ToString() => "Event " + EventDefinition.Name;
}
}
diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs
index 2ac6bfe2b..02b248f85 100644
--- a/ILSpy/TreeNodes/FieldTreeNode.cs
+++ b/ILSpy/TreeNodes/FieldTreeNode.cs
@@ -18,9 +18,12 @@
using System;
+using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
+using ILSpy.Languages;
+
namespace ILSpy.TreeNodes
{
sealed class FieldTreeNode : ILSpyTreeNode
@@ -37,6 +40,9 @@ namespace ILSpy.TreeNodes
Images.Images.GetOverlay(FieldDefinition.Accessibility), FieldDefinition.IsStatic);
public override bool ShowExpander => false;
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ => language.DecompileField(FieldDefinition, output, options);
+
public override string ToString() => "Field " + FieldDefinition.Name;
}
}
diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs
index b7f473424..9862e3dbe 100644
--- a/ILSpy/TreeNodes/ILSpyTreeNode.cs
+++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs
@@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+using ICSharpCode.Decompiler;
using ICSharpCode.ILSpyX.TreeView;
using ILSpy.AppEnv;
@@ -35,5 +36,15 @@ namespace ILSpy.TreeNodes
=> cachedLanguageService ??= AppComposition.Current.GetExport();
public Language Language => LanguageService.CurrentLanguage;
+
+ ///
+ /// Renders this node's decompiled representation to using
+ /// . Default writes a stub comment so any node we forgot to
+ /// override still produces *something*.
+ ///
+ public virtual void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ language.WriteCommentLine(output, Text?.ToString() ?? GetType().Name);
+ }
}
}
diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs
index 8c198d056..6bec54357 100644
--- a/ILSpy/TreeNodes/MethodTreeNode.cs
+++ b/ILSpy/TreeNodes/MethodTreeNode.cs
@@ -18,9 +18,12 @@
using System;
+using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
+using ILSpy.Languages;
+
namespace ILSpy.TreeNodes
{
sealed class MethodTreeNode : ILSpyTreeNode
@@ -48,6 +51,9 @@ namespace ILSpy.TreeNodes
public override bool ShowExpander => false;
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ => language.DecompileMethod(MethodDefinition, output, options);
+
// Stable identity for SessionSettings.ActiveTreeViewPath; matches the WPF host's format.
public override string ToString()
=> "Method " + new ICSharpCode.Decompiler.IL.ILAmbience {
diff --git a/ILSpy/TreeNodes/NamespaceTreeNode.cs b/ILSpy/TreeNodes/NamespaceTreeNode.cs
index 170d96045..55b2b8bde 100644
--- a/ILSpy/TreeNodes/NamespaceTreeNode.cs
+++ b/ILSpy/TreeNodes/NamespaceTreeNode.cs
@@ -19,7 +19,12 @@
using System;
using System.Linq;
+using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.Decompiler.TypeSystem;
+using ICSharpCode.ILSpyX;
+
+using ILSpy.Languages;
namespace ILSpy.TreeNodes
{
@@ -55,5 +60,18 @@ namespace ILSpy.TreeNodes
foreach (var t in types)
Children.Add(new TypeTreeNode(t, module));
}
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ var typeSystem = module.GetTypeSystemOrNull();
+ if (typeSystem == null)
+ {
+ language.WriteCommentLine(output, "(type system unavailable)");
+ return;
+ }
+ var types = typeSystem.MainModule.TypeDefinitions
+ .Where(t => t.Namespace == name && t.DeclaringTypeDefinition == null);
+ language.DecompileNamespace(name, types, output, options);
+ }
}
}
diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs
index 7f2cc6759..516a8e4ae 100644
--- a/ILSpy/TreeNodes/PropertyTreeNode.cs
+++ b/ILSpy/TreeNodes/PropertyTreeNode.cs
@@ -18,9 +18,12 @@
using System;
+using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
+using ILSpy.Languages;
+
namespace ILSpy.TreeNodes
{
sealed class PropertyTreeNode : ILSpyTreeNode
@@ -37,6 +40,9 @@ namespace ILSpy.TreeNodes
Images.Images.GetOverlay(PropertyDefinition.Accessibility), PropertyDefinition.IsStatic);
public override bool ShowExpander => false;
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ => language.DecompileProperty(PropertyDefinition, output, options);
+
public override string ToString()
=> "Property " + new ICSharpCode.Decompiler.IL.ILAmbience {
ConversionFlags = ConversionFlags.ShowTypeParameterList
diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs
index 6a4b4a616..54c40ee44 100644
--- a/ILSpy/TreeNodes/TypeTreeNode.cs
+++ b/ILSpy/TreeNodes/TypeTreeNode.cs
@@ -26,6 +26,8 @@ using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX;
+using ILSpy.Languages;
+
namespace ILSpy.TreeNodes
{
sealed class TypeTreeNode : ILSpyTreeNode
@@ -71,6 +73,15 @@ namespace ILSpy.TreeNodes
public override bool CanExpandRecursively => true;
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ var typeDef = ResolveTypeDefinition();
+ if (typeDef != null)
+ language.DecompileType(typeDef, output, options);
+ else
+ language.WriteCommentLine(output, "(could not resolve type)");
+ }
+
// Stable identity for SessionSettings.ActiveTreeViewPath. ReflectionName is
// language-independent.
public override string ToString()