[closes gh-124] Moved IL comments to a tooltip + base work for MirrorSharp infotips.

This commit is contained in:
Andrey Shchekin 2017-06-14 23:47:30 +12:00
Родитель 20bee87b2b
Коммит 1f37f4a282
9 изменённых файлов: 385 добавлений и 315 удалений

Просмотреть файл

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.IO;
using System.Threading;
using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
@ -15,7 +12,7 @@ namespace SharpLab.Server.Decompilation {
var output = new CustomizableIndentPlainTextOutput(codeWriter) {
IndentationString = " "
};
var disassembler = new ReflectionDisassembler(new ILCommentingTextOutput(output, 30), false, new CancellationToken());
var disassembler = new ReflectionDisassembler(output, false, CancellationToken.None);
disassembler.WriteModuleContents(assembly.MainModule);
}

Просмотреть файл

@ -1,305 +0,0 @@
using System;
using System.Collections.Generic;
using AshMind.Extensions;
using ICSharpCode.Decompiler;
using ICSharpCode.NRefactory;
using Mono.Cecil.Cil;
namespace SharpLab.Server.Decompilation.Internal {
public class ILCommentingTextOutput : ITextOutput {
private readonly ITextOutput _inner;
private readonly int _commentMinColumn;
private int _currentLineLength;
private string _curentComment;
public ILCommentingTextOutput(ITextOutput inner, int commentMinColumn) {
if (inner == null)
throw new ArgumentNullException(nameof(inner));
_inner = inner;
_commentMinColumn = commentMinColumn;
}
public TextLocation Location => _inner.Location;
public void Indent() {
_inner.Indent();
}
public void Unindent() {
_inner.Unindent();
}
public void Write(char ch) {
_inner.Write(ch);
_currentLineLength += 1;
}
public void Write(string text) {
_inner.Write(text);
_currentLineLength += text.Length;
}
public void WriteLine() {
WriteComment();
_inner.WriteLine();
_currentLineLength = 0;
}
public void WriteDefinition(string text, object definition, bool isLocal = true) {
_inner.WriteDefinition(text, definition, isLocal);
_currentLineLength += text.Length;
}
public void WriteReference(string text, object reference, bool isLocal = false) {
UpdateCurrentCommentFrom(reference);
_inner.WriteReference(text, reference, isLocal);
_currentLineLength += text.Length;
}
void ITextOutput.MarkFoldStart(string collapsedText, bool defaultCollapsed) => _inner.MarkFoldStart(collapsedText, defaultCollapsed);
void ITextOutput.MarkFoldEnd() => _inner.MarkFoldEnd();
void ITextOutput.AddDebuggerMemberMapping(MemberMapping memberMapping) => _inner.AddDebuggerMemberMapping(memberMapping);
private void UpdateCurrentCommentFrom(object reference) {
if (!(reference is OpCode))
return;
var comment = Comments.GetValueOrDefault((OpCode)reference);
if (comment != null)
_curentComment = comment;
}
private void WriteComment() {
if (_curentComment == null)
return;
_inner.Write(new string(' ', Math.Max(_commentMinColumn - _currentLineLength, 1)));
_inner.Write($"// {_curentComment}");
_curentComment = null;
}
private static readonly IReadOnlyDictionary<OpCode, string> Comments = new Dictionary<OpCode, string> {
[OpCodes.Add] = "Add two values, returning a new value",
[OpCodes.Add_Ovf] = "Add signed integer values with overflow check",
[OpCodes.Add_Ovf_Un] = "Add unsigned integer values with overflow check",
[OpCodes.And] = "Bitwise AND of two integral values, returns an integral value",
[OpCodes.Arglist] = "Return argument list handle for the current method",
[OpCodes.Beq] = "Branch to target if equal",
[OpCodes.Beq_S] = "Branch to target if equal, short form",
[OpCodes.Bge] = "Branch to target if greater than or equal to",
[OpCodes.Bge_S] = "Branch to target if greater than or equal to, short form",
[OpCodes.Bge_Un] = "Branch to target if greater than or equal to (unsigned or unordered)",
[OpCodes.Bge_Un_S] = "Branch to target if greater than or equal to (unsigned or unordered), short form",
[OpCodes.Bgt] = "Branch to target if greater than",
[OpCodes.Bgt_S] = "Branch to target if greater than, short form",
[OpCodes.Bgt_Un] = "Branch to target if greater than (unsigned or unordered)",
[OpCodes.Bgt_Un_S] = "Branch to target if greater than (unsigned or unordered), short form",
[OpCodes.Ble] = "Branch to target if less than or equal to",
[OpCodes.Ble_S] = "Branch to target if less than or equal to, short form",
[OpCodes.Ble_Un] = "Branch to target if less than or equal to (unsigned or unordered)",
[OpCodes.Ble_Un_S] = "Branch to target if less than or equal to (unsigned or unordered), short form",
[OpCodes.Blt] = "Branch to target if less than",
[OpCodes.Blt_S] = "Branch to target if less than, short form",
[OpCodes.Blt_Un] = "Branch to target if less than (unsigned or unordered)",
[OpCodes.Blt_Un_S] = "Branch to target if less than (unsigned or unordered), short form",
[OpCodes.Bne_Un] = "Branch to target if unequal or unordered",
[OpCodes.Bne_Un_S] = "Branch to target if unequal or unordered, short form",
[OpCodes.Box] = "Convert a boxable value to its boxed form",
[OpCodes.Br] = "Branch to target",
[OpCodes.Br_S] = "Branch to target, short form",
[OpCodes.Break] = "Inform a debugger that a breakpoint has been reached",
[OpCodes.Brfalse] = "Branch to target if value is zero (false)",
[OpCodes.Brfalse_S] = "Branch to target if value is zero (false), short form",
[OpCodes.Brtrue] = "Branch to target if value is non-zero (true)",
[OpCodes.Brtrue_S] = "Branch to target if value is non-zero (true), short form",
[OpCodes.Call] = "Call method",
[OpCodes.Call] = "Call method indicated on the stack with arguments",
[OpCodes.Callvirt] = "Call a method associated with an object",
[OpCodes.Castclass] = "Cast obj to class",
[OpCodes.Ceq] = "Push 1 (of type int32) if value1 equals value2, else push 0",
[OpCodes.Cgt] = "Push 1 (of type int32) if value1 > value2, else push 0",
[OpCodes.Cgt_Un] = "Push 1 (of type int32) if value1 > value2, unsigned or unordered, else push 0",
[OpCodes.Ckfinite] = "Throw ArithmeticException if value is not a finite number",
[OpCodes.Clt] = "Push 1 (of type int32) if value1 < value2, else push 0",
[OpCodes.Clt_Un] = "Push 1 (of type int32) if value1 < value2, unsigned or unordered, else push 0",
[OpCodes.Constrained] = "Call a virtual method on a type constrained to be type T",
[OpCodes.Conv_I] = "Convert to native int, pushing native int on stack",
[OpCodes.Conv_I1] = "Convert to int8, pushing int32 on stack",
[OpCodes.Conv_I2] = "Convert to int16, pushing int32 on stack",
[OpCodes.Conv_I4] = "Convert to int32, pushing int32 on stack",
[OpCodes.Conv_I8] = "Convert to int64, pushing int64 on stack",
[OpCodes.Conv_Ovf_I] = "Convert to a native int (on the stack as native int) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I_Un] = "Convert unsigned to a native int (on the stack as native int) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I1] = "Convert to an int8 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I1_Un] = "Convert unsigned to an int8 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I2] = "Convert to an int16 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I2_Un] = "Convert unsigned to an int16 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I4] = "Convert to an int32 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I4_Un] = "Convert unsigned to an int32 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I8] = "Convert to an int64 (on the stack as int64) and throw an exception on overflow",
[OpCodes.Conv_Ovf_I8_Un] = "Convert unsigned to an int64 (on the stack as int64) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U] = "Convert to a native unsigned int (on the stack as native int) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U_Un] = "Convert unsigned to a native unsigned int (on the stack as native int) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U1] = "Convert to an unsigned int8 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U1_Un] = "Convert unsigned to an unsigned int8 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U2] = "Convert to an unsigned int16 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U2_Un] = "Convert unsigned to an unsigned int16 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U4] = "Convert to an unsigned int32 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U4_Un] = "Convert unsigned to an unsigned int32 (on the stack as int32) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U8] = "Convert to an unsigned int64 (on the stack as int64) and throw an exception on overflow",
[OpCodes.Conv_Ovf_U8_Un] = "Convert unsigned to an unsigned int64 (on the stack as int64) and throw an exception on overflow",
[OpCodes.Conv_R_Un] = "Convert unsigned integer to floating-point, pushing F on stack",
[OpCodes.Conv_R4] = "Convert to float32, pushing F on stack",
[OpCodes.Conv_R8] = "Convert to float64, pushing F on stack",
[OpCodes.Conv_U] = "Convert to native unsigned int, pushing native int on stack",
[OpCodes.Conv_U1] = "Convert to unsigned int8, pushing int32 on stack",
[OpCodes.Conv_U2] = "Convert to unsigned int16, pushing int32 on stack",
[OpCodes.Conv_U4] = "Convert to unsigned int32, pushing int32 on stack",
[OpCodes.Conv_U8] = "Convert to unsigned int64, pushing int64 on stack",
[OpCodes.Cpblk] = "Copy data from memory to memory",
[OpCodes.Cpobj] = "Copy a value type from src to dest",
[OpCodes.Div] = "Divide two values to return a quotient or floating-point result",
[OpCodes.Div_Un] = "Divide two values, unsigned, returning a quotient",
[OpCodes.Dup] = "Duplicate the value on the top of the stack",
[OpCodes.Endfilter] = "End an exception handling filter clause",
[OpCodes.Endfinally] = "End finally clause of an exception block",
[OpCodes.Initblk] = "Set all bytes in a block of memory to a given byte value",
[OpCodes.Initobj] = "Initialize the value at address dest",
[OpCodes.Isinst] = "Test if obj is an instance of class, returning null or an instance of that class or interface",
[OpCodes.Jmp] = "Exit current method and jump to the specified method",
[OpCodes.Ldarg] = "Load argument numbered num onto the stack",
[OpCodes.Ldarg_0] = "Load argument 0 onto the stack",
[OpCodes.Ldarg_1] = "Load argument 1 onto the stack",
[OpCodes.Ldarg_2] = "Load argument 2 onto the stack",
[OpCodes.Ldarg_3] = "Load argument 3 onto the stack",
[OpCodes.Ldarg_S] = "Load argument numbered num onto the stack, short form",
[OpCodes.Ldarga] = "Fetch the address of argument argNum",
[OpCodes.Ldarga_S] = "Fetch the address of argument argNum, short form",
[OpCodes.Ldc_I4] = "Push num of type int32 onto the stack as int32",
[OpCodes.Ldc_I4_0] = "Push 0 onto the stack as int32",
[OpCodes.Ldc_I4_1] = "Push 1 onto the stack as int32",
[OpCodes.Ldc_I4_2] = "Push 2 onto the stack as int32",
[OpCodes.Ldc_I4_3] = "Push 3 onto the stack as int32",
[OpCodes.Ldc_I4_4] = "Push 4 onto the stack as int32",
[OpCodes.Ldc_I4_5] = "Push 5 onto the stack as int32",
[OpCodes.Ldc_I4_6] = "Push 6 onto the stack as int32",
[OpCodes.Ldc_I4_7] = "Push 7 onto the stack as int32",
[OpCodes.Ldc_I4_8] = "Push 8 onto the stack as int32",
[OpCodes.Ldc_I4_M1] = "Push -1 onto the stack as int32",
[OpCodes.Ldc_I4_S] = "Push num onto the stack as int32, short form",
[OpCodes.Ldc_I8] = "Push num of type int64 onto the stack as int64",
[OpCodes.Ldc_R4 ] = "Push num of type float32 onto the stack as F",
[OpCodes.Ldc_R8] = "Push num of type float64 onto the stack as F",
[OpCodes.Ldelem_Any] = "Load the element at index onto the top of the stack",
[OpCodes.Ldelem_I] = "Load the element with type native int at index onto the top of the stack as a native int",
[OpCodes.Ldelem_I1] = "Load the element with type int8 at index onto the top of the stack as an int32",
[OpCodes.Ldelem_I2] = "Load the element with type int16 at index onto the top of the stack as an int32",
[OpCodes.Ldelem_I4] = "Load the element with type int32 at index onto the top of the stack as an int32",
[OpCodes.Ldelem_I8] = "Load the element with type int64 at index onto the top of the stack as an int64",
[OpCodes.Ldelem_R4] = "Load the element with type float32 at index onto the top of the stack as an F",
[OpCodes.Ldelem_R8] = "Load the element with type float64 at index onto the top of the stack as an F",
[OpCodes.Ldelem_Ref] = "Load the element at index onto the top of the stack as an O. The type of the O is the same as the element type of the array pushed on the CIL stack",
[OpCodes.Ldelem_U1] = "Load the element with type unsigned int8 at index onto the top of the stack as an int32",
[OpCodes.Ldelem_U2] = "Load the element with type unsigned int16 at index onto the top of the stack as an int32",
[OpCodes.Ldelem_U4] = "Load the element with type unsigned int32 at index onto the top of the stack as an int32",
[OpCodes.Ldelema] = "Load the address of element at index onto the top of the stack",
[OpCodes.Ldfld] = "Push the value of field of object (or value type) obj, onto the stack",
[OpCodes.Ldflda] = "Push the address of field of object obj on the stack",
[OpCodes.Ldftn] = "Push a pointer to a method referenced by method, on the stack",
[OpCodes.Ldind_I] = "Indirect load value of type native int as native int on the stack",
[OpCodes.Ldind_I1] = "Indirect load value of type int8 as int32 on the stack",
[OpCodes.Ldind_I2] = "Indirect load value of type int16 as int32 on the stack",
[OpCodes.Ldind_I4] = "Indirect load value of type int32 as int32 on the stack",
[OpCodes.Ldind_I8] = "Indirect load value of type int64 as int64 on the stack",
[OpCodes.Ldind_R4] = "Indirect load value of type float32 as F on the stack",
[OpCodes.Ldind_R8] = "Indirect load value of type float64 as F on the stack",
[OpCodes.Ldind_Ref] = "Indirect load value of type object ref as O on the stack",
[OpCodes.Ldind_U1] = "Indirect load value of type unsigned int8 as int32 on the stack",
[OpCodes.Ldind_U2] = "Indirect load value of type unsigned int16 as int32 on the stack",
[OpCodes.Ldind_U4] = "Indirect load value of type unsigned int32 as int32 on the stack",
[OpCodes.Ldlen] = "Push the length (of type native unsigned int) of array on the stack",
[OpCodes.Ldloc] = "Load local variable of index indx onto stack",
[OpCodes.Ldloc_0] = "Load local variable 0 onto stack",
[OpCodes.Ldloc_1] = "Load local variable 1 onto stack",
[OpCodes.Ldloc_2] = "Load local variable 2 onto stack",
[OpCodes.Ldloc_3] = "Load local variable 3 onto stack",
[OpCodes.Ldloc_S] = "Load local variable of index indx onto stack, short form",
[OpCodes.Ldloca] = "Load address of local variable with index indx",
[OpCodes.Ldloca_S] = "Load address of local variable with index indx, short form",
[OpCodes.Ldnull] = "Push a null reference on the stack",
[OpCodes.Ldobj] = "Copy the value stored at address src to the stack",
[OpCodes.Ldsfld] = "Push the value of field on the stack",
[OpCodes.Ldsflda] = "Push the address of the static field, field, on the stack",
[OpCodes.Ldstr] = "Push a string object for the literal string",
[OpCodes.Ldtoken] = "Convert metadata token to its runtime representation",
[OpCodes.Ldvirtftn] = "Push address of virtual method on the stack",
[OpCodes.Leave] = "Exit a protected region of code",
[OpCodes.Leave_S] = "Exit a protected region of code, short form",
[OpCodes.Localloc] = "Allocate space from the local memory pool",
[OpCodes.Mkrefany] = "Push a typed reference to ptr of type class onto the stack",
[OpCodes.Mul] = "Multiply values",
[OpCodes.Mul_Ovf] = "Multiply signed integer values. Signed result shall fit in same size",
[OpCodes.Mul_Ovf_Un] = "Multiply unsigned integer values. Unsigned result shall fit in same size",
[OpCodes.Neg] = "Negate value",
[OpCodes.Newarr] = "Create a new array with elements of type etype",
[OpCodes.Newobj] = "Allocate an uninitialized object or value type and call ctor",
[OpCodes.No] = "The specified fault check(s) normally performed as part of the execution of the subsequent instruction can/shall be skipped",
[OpCodes.Nop] = "Do nothing (No operation)",
[OpCodes.Not] = "Bitwise complement (logical not)",
[OpCodes.Or] = "Bitwise OR of two integer values, returns an integer",
[OpCodes.Pop] = "Pop value from the stack",
[OpCodes.Readonly] = "Specify that the subsequent array address operation performs no type check at runtime, and that it returns a controlled-mutability managed pointer",
[OpCodes.Refanytype] = "Push the type token stored in a typed reference",
[OpCodes.Refanyval] = "Push the address stored in a typed reference",
[OpCodes.Rem] = "Remainder when dividing one value by another",
[OpCodes.Rem_Un] = "Remainder when dividing one unsigned value by another",
[OpCodes.Ret] = "Return from method, possibly with a value",
[OpCodes.Rethrow] = "Rethrow the current exception",
[OpCodes.Shl] = "Shift an integer left (shifting in zeros), return an integer",
[OpCodes.Shr] = "Shift an integer right (shift in sign), return an integer",
[OpCodes.Shr_Un] = "Shift an integer right (shift in zero), return an integer",
[OpCodes.Sizeof] = "Push the size, in bytes, of a type as an unsigned int32",
[OpCodes.Starg] = "Store value to the argument numbered num",
[OpCodes.Starg_S] = "Store value to the argument numbered num, short form",
[OpCodes.Stelem_Any] = "Replace array element at index with the value on the stack",
[OpCodes.Stelem_I] = "Replace array element at index with the i value on the stack",
[OpCodes.Stelem_I1] = "Replace array element at index with the int8 value on the stack",
[OpCodes.Stelem_I2] = "Replace array element at index with the int16 value on the stack",
[OpCodes.Stelem_I4] = "Replace array element at index with the int32 value on the stack",
[OpCodes.Stelem_I8] = "Replace array element at index with the int64 value on the stack",
[OpCodes.Stelem_R4] = "Replace array element at index with the float32 value on the stack",
[OpCodes.Stelem_R8] = "Replace array element at index with the float64 value on the stack",
[OpCodes.Stelem_Ref] = "Replace array element at index with the ref value on the stack",
[OpCodes.Stfld] = "Replace the value of field of the object obj with value",
[OpCodes.Stind_I] = "Store value of type native int into memory at address",
[OpCodes.Stind_I1] = "Store value of type int8 into memory at address",
[OpCodes.Stind_I2] = "Store value of type int16 into memory at address",
[OpCodes.Stind_I4] = "Store value of type int32 into memory at address",
[OpCodes.Stind_I8] = "Store value of type int64 into memory at address",
[OpCodes.Stind_R4] = "Store value of type float32 into memory at address",
[OpCodes.Stind_R8] = "Store value of type float64 into memory at address",
[OpCodes.Stind_Ref] = "Store value of type object ref (type O) into memory at address",
[OpCodes.Stloc] = "Pop a value from stack into local variable indx",
[OpCodes.Stloc_0] = "Pop a value from stack into local variable 0",
[OpCodes.Stloc_1] = "Pop a value from stack into local variable 1",
[OpCodes.Stloc_2] = "Pop a value from stack into local variable 2",
[OpCodes.Stloc_3] = "Pop a value from stack into local variable 3",
[OpCodes.Stloc_S] = "Pop a value from stack into local variable indx, short form",
[OpCodes.Stobj] = "Store a value of type typeTok at an address",
[OpCodes.Stsfld] = "Replace the value of field with val",
[OpCodes.Sub] = "Subtract value2 from value1, returning a new value",
[OpCodes.Sub_Ovf] = "Subtract native int from a native int. Signed result shall fit in same size",
[OpCodes.Sub_Ovf_Un] = "Subtract native unsigned int from a native unsigned int. Unsigned result shall fit in same size",
[OpCodes.Switch] = "Jump to one of n values",
[OpCodes.Tail] = "Subsequent call terminates current method",
[OpCodes.Throw] = "Throw an exception",
[OpCodes.Unaligned] = "Subsequent pointer instruction might be unaligned",
[OpCodes.Unbox] = "Extract a value-type from obj, its boxed representation",
[OpCodes.Unbox_Any] = "Extract a value-type from obj, its boxed representation",
[OpCodes.Volatile] = "Subsequent pointer reference is volatile",
[OpCodes.Xor] = "Bitwise XOR of integer values, returns an integer"
};
}
}

Просмотреть файл

@ -18,9 +18,9 @@
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0 // Load argument 0 onto the stack
IL_0001: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments
IL_0006: ret // Return from method, possibly with a value
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Simple::.ctor
} // end of class Simple

248
source/WebApp/js/ui/codemirror/addon-cil-infotip.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,248 @@
(function(mod) {
if (typeof exports === "object" && typeof module === "object") // CommonJS
mod(require("codemirror"));
else if (typeof define === "function" && define.amd) // AMD
define(["codemirror"], mod);
else // Plain browser env
mod(window.CodeMirror);
})(function(CodeMirror) {
"use strict";
var instructions = {
"add": "Add two values, returning a new value",
"add.ovf": "Add signed integer values with overflow check",
"add.ovf.un": "Add unsigned integer values with overflow check",
"and": "Bitwise AND of two integral values, returns an integral value",
"arglist": "Return argument list handle for the current method",
"beq": "Branch to target if equal",
"beq.s": "Branch to target if equal, short form",
"bge": "Branch to target if greater than or equal to",
"bge.s": "Branch to target if greater than or equal to, short form",
"bge.un": "Branch to target if greater than or equal to (unsigned or unordered)",
"bge.un.s": "Branch to target if greater than or equal to (unsigned or unordered), short form",
"bgt": "Branch to target if greater than",
"bgt.s": "Branch to target if greater than, short form",
"bgt.un": "Branch to target if greater than (unsigned or unordered)",
"bgt.un.s": "Branch to target if greater than (unsigned or unordered), short form",
"ble": "Branch to target if less than or equal to",
"ble.s": "Branch to target if less than or equal to, short form",
"ble.un": "Branch to target if less than or equal to (unsigned or unordered)",
"ble.un.s": "Branch to target if less than or equal to (unsigned or unordered), short form",
"blt": "Branch to target if less than",
"blt.s": "Branch to target if less than, short form",
"blt.un": "Branch to target if less than (unsigned or unordered)",
"blt.un.s": "Branch to target if less than (unsigned or unordered), short form",
"bne.un": "Branch to target if unequal or unordered",
"bne.un.s": "Branch to target if unequal or unordered, short form",
"box": "Convert a boxable value to its boxed form",
"br": "Branch to target",
"br.s": "Branch to target, short form",
"break": "Inform a debugger that a breakpoint has been reached",
"brfalse": "Branch to target if value is zero (false)",
"brfalse.s": "Branch to target if value is zero (false), short form",
"brinst": "Branch to target if value is a non-null object reference (alias for brtrue)",
"brinst.s": "Branch to target if value is a non-null object reference, short form (alias for brtrue.s)",
"brnull": "Branch to target if value is null (alias for brfalse)",
"brnull.s": "Branch to target if value is null (alias for brfalse.s), short form",
"brtrue": "Branch to target if value is non-zero (true)",
"brtrue.s": "Branch to target if value is non-zero (true), short form",
"brzero": "Branch to target if value is zero (alias for brfalse)",
"brzero.s": "Branch to target if value is zero (alias for brfalse.s), short form",
"call": "Call method indicated on the stack with arguments",
"callvirt": "Call a late-bound method on an object",
"castclass": "Cast obj to class",
"ceq": "Push 1 (of type int32) if value1 equals value2, else push 0",
"cgt": "Push 1 (of type int32) if value1 > value2, else push 0",
"cgt.un": "Push 1 (of type int32) if value1 > value2, unsigned or unordered, else push 0",
"ckfinite": "Throw ArithmeticException if value is not a finite number",
"clt": "Push 1 (of type int32) if value1 < value2, else push 0",
"clt.un": "Push 1 (of type int32) if value1 < value2, unsigned or unordered, else push 0",
"constrained": "Call a virtual method on a type constrained to be type T",
"conv.i": "Convert to native int, pushing native int on stack",
"conv.i1": "Convert to int8, pushing int32 on stack",
"conv.i2": "Convert to int16, pushing int32 on stack",
"conv.i4": "Convert to int32, pushing int32 on stack",
"conv.i8": "Convert to int64, pushing int64 on stack",
"conv.ovf.i": "Convert to a native int (on the stack as native int) and throw an exception on overflow",
"conv.ovf.i.un": "Convert unsigned to a native int (on the stack as native int) and throw an exception on overflow",
"conv.ovf.i1": "Convert to an int8 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.i1.un": "Convert unsigned to an int8 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.i2": "Convert to an int16 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.i2.un": "Convert unsigned to an int16 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.i4": "Convert to an int32 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.i4.un": "Convert unsigned to an int32 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.i8": "Convert to an int64 (on the stack as int64) and throw an exception on overflow",
"conv.ovf.i8.un": "Convert unsigned to an int64 (on the stack as int64) and throw an exception on overflow",
"conv.ovf.u": "Convert to a native unsigned int (on the stack as native int) and throw an exception on overflow",
"conv.ovf.u.un": "Convert unsigned to a native unsigned int (on the stack as native int) and throw an exception on overflow",
"conv.ovf.u1": "Convert to an unsigned int8 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.u1.un": "Convert unsigned to an unsigned int8 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.u2": "Convert to an unsigned int16 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.u2.un": "Convert unsigned to an unsigned int16 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.u4": "Convert to an unsigned int32 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.u4.un": "Convert unsigned to an unsigned int32 (on the stack as int32) and throw an exception on overflow",
"conv.ovf.u8": "Convert to an unsigned int64 (on the stack as int64) and throw an exception on overflow",
"conv.ovf.u8.un": "Convert unsigned to an unsigned int64 (on the stack as int64) and throw an exception on overflow",
"conv.r.un": "Convert unsigned integer to floating-point, pushing F on stack",
"conv.r4": "Convert to float32, pushing F on stack",
"conv.r8": "Convert to float64, pushing F on stack",
"conv.u": "Convert to native unsigned int, pushing native int on stack",
"conv.u1": "Convert to unsigned int8, pushing int32 on stack",
"conv.u2": "Convert to unsigned int16, pushing int32 on stack",
"conv.u4": "Convert to unsigned int32, pushing int32 on stack",
"conv.u8": "Convert to unsigned int64, pushing int64 on stack",
"cpblk": "Copy data from memory to memory",
"cpobj": "Copy a value type from src to dest",
"div": "Divide two values to return a quotient or floating-point result",
"div.un": "Divide two values, unsigned, returning a quotient",
"dup": "Duplicate the value on the top of the stack",
"endfault": "End fault clause of an exception block",
"endfilter": "End an exception handling filter clause",
"endfinally": "End finally clause of an exception block",
"initblk": "Set all bytes in a block of memory to a given byte value",
"initobj": "Initialize the value at address dest",
"isinst": "Test if obj is an instance of class, returning null or an instance of that class or interface",
"jmp": "Exit current method and jump to the specified method",
"ldarg": "Load argument numbered num onto the stack",
"ldarg.0": "Load argument 0 onto the stack",
"ldarg.1": "Load argument 1 onto the stack",
"ldarg.2": "Load argument 2 onto the stack",
"ldarg.3": "Load argument 3 onto the stack",
"ldarg.s": "Load argument numbered num onto the stack, short form",
"ldarga": "Fetch the address of argument argNum",
"ldarga.s": "Fetch the address of argument argNum, short form",
"ldc.i4": "Push num of type int32 onto the stack as int32",
"ldc.i4.0": "Push 0 onto the stack as int32",
"ldc.i4.1": "Push 1 onto the stack as int32",
"ldc.i4.2": "Push 2 onto the stack as int32",
"ldc.i4.3": "Push 3 onto the stack as int32",
"ldc.i4.4": "Push 4 onto the stack as int32",
"ldc.i4.5": "Push 5 onto the stack as int32",
"ldc.i4.6": "Push 6 onto the stack as int32",
"ldc.i4.7": "Push 7 onto the stack as int32",
"ldc.i4.8": "Push 8 onto the stack as int32",
"ldc.i4.m1": "Push -1 onto the stack as int32",
"ldc.i4.M1": "Push -1 of type int32 onto the stack as int32 (alias for ldc.i4.m1)",
"ldc.i4.s": "Push num onto the stack as int32, short form",
"ldc.i8": "Push num of type int64 onto the stack as int64",
"ldc.r4 ": "Push num of type float32 onto the stack as F",
"ldc.r8": "Push num of type float64 onto the stack as F",
"ldelem": "Load the element at index onto the top of the stack",
"ldelem.i": "Load the element with type native int at index onto the top of the stack as a native int",
"ldelem.i1": "Load the element with type int8 at index onto the top of the stack as an int32",
"ldelem.i2": "Load the element with type int16 at index onto the top of the stack as an int32",
"ldelem.i4": "Load the element with type int32 at index onto the top of the stack as an int32",
"ldelem.i8": "Load the element with type int64 at index onto the top of the stack as an int64",
"ldelem.r4": "Load the element with type float32 at index onto the top of the stack as an F",
"ldelem.r8": "Load the element with type float64 at index onto the top of the stack as an F",
"ldelem.ref": "Load the element at index onto the top of the stack as an O. The type of the O is the same as the element type of the array pushed on the CIL stack",
"ldelem.u1": "Load the element with type unsigned int8 at index onto the top of the stack as an int32",
"ldelem.u2": "Load the element with type unsigned int16 at index onto the top of the stack as an int32",
"ldelem.u4": "Load the element with type unsigned int32 at index onto the top of the stack as an int32",
"ldelem.u8": "Load the element with type unsigned int64 at index onto the top of the stack as an int64 (alias for ldelem.i8)",
"ldelema": "Load the address of element at index onto the top of the stack",
"ldfld": "Push the value of field of object (or value type) obj, onto the stack",
"ldflda": "Push the address of field of object obj on the stack",
"ldftn": "Push a pointer to a method referenced by method, on the stack",
"ldind.i": "Indirect load value of type native int as native int on the stack",
"ldind.i1": "Indirect load value of type int8 as int32 on the stack",
"ldind.i2": "Indirect load value of type int16 as int32 on the stack",
"ldind.i4": "Indirect load value of type int32 as int32 on the stack",
"ldind.i8": "Indirect load value of type int64 as int64 on the stack",
"ldind.r4": "Indirect load value of type float32 as F on the stack",
"ldind.r8": "Indirect load value of type float64 as F on the stack",
"ldind.ref": "Indirect load value of type object ref as O on the stack",
"ldind.u1": "Indirect load value of type unsigned int8 as int32 on the stack",
"ldind.u2": "Indirect load value of type unsigned int16 as int32 on the stack",
"ldind.u4": "Indirect load value of type unsigned int32 as int32 on the stack",
"ldind.u8": "Indirect load value of type unsigned int64 as int64 on the stack (alias for ldind.i8)",
"ldlen": "Push the length (of type native unsigned int) of array on the stack",
"ldloc": "Load local variable of index indx onto stack",
"ldloc.0": "Load local variable 0 onto stack",
"ldloc.1": "Load local variable 1 onto stack",
"ldloc.2": "Load local variable 2 onto stack",
"ldloc.3": "Load local variable 3 onto stack",
"ldloc.s": "Load local variable of index indx onto stack, short form",
"ldloca": "Load address of local variable with index indx",
"ldloca.s": "Load address of local variable with index indx, short form",
"ldnull": "Push a null reference on the stack",
"ldobj": "Copy the value stored at address src to the stack",
"ldsfld": "Push the value of field on the stack",
"ldsflda": "Push the address of the static field, field, on the stack",
"ldstr": "Push a string object for the literal string",
"ldtoken": "Convert metadata token to its runtime representation",
"ldvirtftn": "Push address of virtual method on the stack",
"leave": "Exit a protected region of code",
"leave.s": "Exit a protected region of code, short form",
"localloc": "Allocate space from the local memory pool",
"mkrefany": "Push a typed reference to ptr of type class onto the stack",
"mul": "Multiply values",
"mul.ovf": "Multiply signed integer values. Signed result shall fit in same size",
"mul.ovf.un": "Multiply unsigned integer values. Unsigned result shall fit in same size",
"neg": "Negate value",
"newarr": "Create a new array with elements of type etype",
"newobj": "Allocate an uninitialized object or value type and call ctor",
"no": "The specified fault check(s) normally performed as part of the execution of the subsequent instruction can/shall be skipped",
"nop": "Do nothing (No operation)",
"not": "Bitwise complement (logical not)",
"or": "Bitwise OR of two integer values, returns an integer",
"pop": "Pop value from the stack",
"readonly": "Specify that the subsequent array address operation performs no type check at runtime, and that it returns a controlled-mutability managed pointer",
"refanytype": "Push the type token stored in a typed reference",
"refanyval": "Push the address stored in a typed reference",
"rem": "Remainder when dividing one value by another",
"rem.un": "Remainder when dividing one unsigned value by another",
"ret": "Return from method, possibly with a value",
"rethrow": "Rethrow the current exception",
"shl": "Shift an integer left (shifting in zeros), return an integer",
"shr": "Shift an integer right (shift in sign), return an integer",
"shr.un": "Shift an integer right (shift in zero), return an integer",
"sizeof": "Push the size, in bytes, of a type as an unsigned int32",
"starg": "Store value to the argument numbered num",
"starg.s": "Store value to the argument numbered num, short form",
"stelem": "Replace array element at index with the value on the stack",
"stelem.i": "Replace array element at index with the i value on the stack",
"stelem.i1": "Replace array element at index with the int8 value on the stack",
"stelem.i2": "Replace array element at index with the int16 value on the stack",
"stelem.i4": "Replace array element at index with the int32 value on the stack",
"stelem.i8": "Replace array element at index with the int64 value on the stack",
"stelem.r4": "Replace array element at index with the float32 value on the stack",
"stelem.r8": "Replace array element at index with the float64 value on the stack",
"stelem.ref": "Replace array element at index with the ref value on the stack",
"stfld": "Replace the value of field of the object obj with value",
"stind.i": "Store value of type native int into memory at address",
"stind.i1": "Store value of type int8 into memory at address",
"stind.i2": "Store value of type int16 into memory at address",
"stind.i4": "Store value of type int32 into memory at address",
"stind.i8": "Store value of type int64 into memory at address",
"stind.r4": "Store value of type float32 into memory at address",
"stind.r8": "Store value of type float64 into memory at address",
"stind.ref": "Store value of type object ref (type O) into memory at address",
"stloc": "Pop a value from stack into local variable indx",
"stloc.0": "Pop a value from stack into local variable 0",
"stloc.1": "Pop a value from stack into local variable 1",
"stloc.2": "Pop a value from stack into local variable 2",
"stloc.3": "Pop a value from stack into local variable 3",
"stloc.s": "Pop a value from stack into local variable indx, short form",
"stobj": "Store a value of type typeTok at an address",
"stsfld": "Replace the value of field with val",
"sub": "Subtract value2 from value1, returning a new value",
"sub.ovf": "Subtract native int from a native int. Signed result shall fit in same size",
"sub.ovf.un": "Subtract native unsigned int from a native unsigned int. Unsigned result shall fit in same size",
"switch": "Jump to one of n values",
"tail": "Subsequent call terminates current method",
"throw": "Throw an exception",
"unaligned": "Subsequent pointer instruction might be unaligned",
"unbox": "Extract a value-type from obj, its boxed representation",
"unbox.any": "Extract a value-type from obj, its boxed representation",
"volatile": "Subsequent pointer reference is volatile",
"xor": "Bitwise XOR of integer values, returns an integer"
};
CodeMirror.registerHelper("infotip", "cil", function(cm, token) {
if (!token || token.type !== "builtin")
return null;
return "<span class='cm-builtin'>" + token.string + "</span>" +
"<div class='CodeMirror-infotip-description'>" + instructions[token.string] + "</div>";
});
});

114
source/WebApp/js/ui/codemirror/addon-infotip.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,114 @@
(function(mod) {
if (typeof exports === "object" && typeof module === "object") // CommonJS
mod(require("codemirror"));
else if (typeof define === "function" && define.amd) // AMD
define(["codemirror"], mod);
else // Plain browser env
mod(window.CodeMirror);
})(function(CodeMirror) {
"use strict";
var tooltip = (function() {
var element;
var ensureElement = function() {
if (element)
return;
element = document.createElement("div");
element.className = "CodeMirror-infotip cm-s-default"; // TODO: dynamic theme based on current cm
element.setAttribute("hidden", "hidden");
CodeMirror.on(element, "click", function() { tooltip.hide(); });
document.getElementsByTagName("body")[0].appendChild(element);
};
return {
show: function(content, x, y) {
if (!this.active) {
ensureElement();
element.removeAttribute("hidden");
}
element.innerHTML = content;
element.style.transform = "translate(" + x + "px, " + y + "px)";
this.active = true;
this.content = content;
},
hide: function() {
if (!this.active || !element)
return;
element.setAttribute("hidden", "hidden");
this.active = false;
}
};
})();
var activeTimeout;
function mousemove(e) {
/* eslint-disable no-invalid-this */
if (activeTimeout) {
clearTimeout(activeTimeout);
}
var wrapper = this;
activeTimeout = setTimeout(function() {
processMoveOrClick.call(wrapper, e);
activeTimeout = null;
}, 100);
}
function mouseout(e) {
var cm = this.CodeMirror;
if (e.target !== cm.getWrapperElement())
return;
tooltip.hide();
}
function click(e) {
processMoveOrClick.call(this, e);
}
function processMoveOrClick(e) {
/* eslint-disable no-invalid-this */
var cm = this.CodeMirror;
var coords = cm.coordsChar({ left: e.x, top: e.y });
var getTipContent = cm.state.infotip.getTipContent || cm.getHelper(coords, "infotip");
if (!getTipContent) {
tooltip.hide();
return;
}
var token = cm.getTokenAt(coords);
var content = getTipContent(cm, token);
if (content == null) {
tooltip.hide();
return;
}
if (tooltip.active && content === tooltip.content)
return;
const tokenStart = cm.cursorCoords(CodeMirror.Pos(coords.line, token.start));
tooltip.show(content, tokenStart.left, tokenStart.bottom);
}
CodeMirror.defineOption("infotip", null, function(cm, options, old) {
var wrapper = cm.getWrapperElement();
var state = cm.state.infotip;
if (old && old !== CodeMirror.Init && state) {
CodeMirror.off(wrapper, "click", click);
CodeMirror.off(wrapper, "mousemove", mousemove);
CodeMirror.off(wrapper, "mouseout", mouseout);
delete cm.state.infotip;
}
if (!options)
return;
state = {
getTipContent: options.getTipContent
};
cm.state.infotip = state;
CodeMirror.on(wrapper, "click", click);
CodeMirror.on(wrapper, "mousemove", mousemove);
CodeMirror.on(wrapper, "mouseout", mouseout);
});
});

3
source/WebApp/js/ui/codemirror/mode-cil.js поставляемый
Просмотреть файл

@ -124,7 +124,8 @@
}
for (var key in grammar) {
if (stream.match(grammar[key])) {
if (stream.match(grammar[key], false)) {
stream.match(/\S+/);
return key;
}
}

Просмотреть файл

@ -5,6 +5,8 @@ import 'codemirror/mode/clike/clike';
import 'codemirror/mode/vb/vb';
import '../codemirror/mode-cil.js';
import '../codemirror/mode-asm.js';
import '../codemirror/addon-infotip.js';
import '../codemirror/addon-cil-infotip.js';
Vue.component('app-mirrorsharp-readonly', {
props: {
@ -25,7 +27,8 @@ Vue.component('app-mirrorsharp-readonly', {
const options = {
readOnly: true,
indentUnit: 4,
mode: modeMap[this.language]
mode: modeMap[this.language],
infotip: {}
};
const cm = CodeMirror.fromTextArea(textarea, options);
this.cm = cm;

Просмотреть файл

@ -5,6 +5,7 @@
@import (inline) '../../node_modules/codemirror/addon/hint/show-hint.css';
@import (inline) '../../node_modules/codemirror-addon-lint-fix/dist/lint-fix.css';
@import (inline) '../../node_modules/mirrorsharp/mirrorsharp.css';
@import (inline) 'codemirror/addon-infotip.css';
textarea, .CodeMirror {
.code-text();

11
source/WebApp/less/imports/codemirror/addon-infotip.css поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
.CodeMirror-infotip {
position: absolute;
z-index: 5000;
padding: 2px 5px;
background: #eee;
border: 1px solid #ddd;
border-radius: 3px;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
}