mirror of https://github.com/icsharpcode/ILSpy.git
3 changed files with 431 additions and 419 deletions
@ -0,0 +1,429 @@
@@ -0,0 +1,429 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.AvalonEdit.Highlighting; |
||||
using ICSharpCode.Decompiler.CSharp; |
||||
using ICSharpCode.Decompiler.CSharp.OutputVisitor; |
||||
using ICSharpCode.Decompiler.CSharp.Syntax; |
||||
using ICSharpCode.Decompiler.TypeSystem; |
||||
|
||||
namespace ICSharpCode.ILSpy |
||||
{ |
||||
class CSharpHighlightingTokenWriter : DecoratingTokenWriter |
||||
{ |
||||
ISmartTextOutput textOutput; |
||||
|
||||
HighlightingColor visibilityKeywordsColor; |
||||
HighlightingColor namespaceKeywordsColor; |
||||
HighlightingColor structureKeywordsColor; |
||||
HighlightingColor gotoKeywordsColor; |
||||
HighlightingColor queryKeywordsColor; |
||||
HighlightingColor exceptionKeywordsColor; |
||||
HighlightingColor checkedKeywordColor; |
||||
HighlightingColor unsafeKeywordsColor; |
||||
HighlightingColor valueTypeKeywordsColor; |
||||
HighlightingColor referenceTypeKeywordsColor; |
||||
HighlightingColor operatorKeywordsColor; |
||||
HighlightingColor parameterModifierColor; |
||||
HighlightingColor modifiersColor; |
||||
HighlightingColor accessorKeywordsColor; |
||||
HighlightingColor attributeKeywordsColor; |
||||
|
||||
HighlightingColor referenceTypeColor; |
||||
HighlightingColor valueTypeColor; |
||||
HighlightingColor interfaceTypeColor; |
||||
HighlightingColor enumerationTypeColor; |
||||
HighlightingColor typeParameterTypeColor; |
||||
HighlightingColor delegateTypeColor; |
||||
|
||||
HighlightingColor methodCallColor; |
||||
HighlightingColor methodDeclarationColor; |
||||
|
||||
HighlightingColor fieldDeclarationColor; |
||||
HighlightingColor fieldAccessColor; |
||||
|
||||
HighlightingColor valueKeywordColor; |
||||
HighlightingColor thisKeywordColor; |
||||
HighlightingColor trueKeywordColor; |
||||
HighlightingColor typeKeywordsColor; |
||||
|
||||
public CSharpHighlightingTokenWriter(TokenWriter decoratedWriter, ISmartTextOutput textOutput) : base(decoratedWriter) |
||||
{ |
||||
this.textOutput = textOutput; |
||||
var highlighting = HighlightingManager.Instance.GetDefinition("C#"); |
||||
|
||||
//this.defaultTextColor = ???;
|
||||
|
||||
this.visibilityKeywordsColor = highlighting.GetNamedColor("Visibility"); |
||||
this.namespaceKeywordsColor = highlighting.GetNamedColor("NamespaceKeywords"); |
||||
this.structureKeywordsColor = highlighting.GetNamedColor("Keywords"); |
||||
this.gotoKeywordsColor = highlighting.GetNamedColor("GotoKeywords"); |
||||
this.queryKeywordsColor = highlighting.GetNamedColor("QueryKeywords"); |
||||
this.exceptionKeywordsColor = highlighting.GetNamedColor("ExceptionKeywords"); |
||||
this.checkedKeywordColor = highlighting.GetNamedColor("CheckedKeyword"); |
||||
this.unsafeKeywordsColor = highlighting.GetNamedColor("UnsafeKeywords"); |
||||
this.valueTypeKeywordsColor = highlighting.GetNamedColor("ValueTypeKeywords"); |
||||
this.referenceTypeKeywordsColor = highlighting.GetNamedColor("ReferenceTypeKeywords"); |
||||
this.operatorKeywordsColor = highlighting.GetNamedColor("OperatorKeywords"); |
||||
this.parameterModifierColor = highlighting.GetNamedColor("ParameterModifiers"); |
||||
this.modifiersColor = highlighting.GetNamedColor("Modifiers"); |
||||
this.accessorKeywordsColor = highlighting.GetNamedColor("GetSetAddRemove"); |
||||
|
||||
this.referenceTypeColor = highlighting.GetNamedColor("ReferenceTypes"); |
||||
this.valueTypeColor = highlighting.GetNamedColor("ValueTypes"); |
||||
this.interfaceTypeColor = highlighting.GetNamedColor("InterfaceTypes"); |
||||
this.enumerationTypeColor = highlighting.GetNamedColor("EnumTypes"); |
||||
this.typeParameterTypeColor = highlighting.GetNamedColor("TypeParameters"); |
||||
this.delegateTypeColor = highlighting.GetNamedColor("DelegateTypes"); |
||||
this.methodDeclarationColor = this.methodCallColor = highlighting.GetNamedColor("MethodCall"); |
||||
//this.eventDeclarationColor = this.eventAccessColor = defaultTextColor;
|
||||
//this.propertyDeclarationColor = this.propertyAccessColor = defaultTextColor;
|
||||
this.fieldDeclarationColor = this.fieldAccessColor = highlighting.GetNamedColor("FieldAccess"); |
||||
//this.variableDeclarationColor = this.variableAccessColor = defaultTextColor;
|
||||
//this.parameterDeclarationColor = this.parameterAccessColor = defaultTextColor;
|
||||
this.valueKeywordColor = highlighting.GetNamedColor("NullOrValueKeywords"); |
||||
this.thisKeywordColor = highlighting.GetNamedColor("ThisOrBaseReference"); |
||||
this.trueKeywordColor = highlighting.GetNamedColor("TrueFalse"); |
||||
this.typeKeywordsColor = highlighting.GetNamedColor("TypeKeywords"); |
||||
this.attributeKeywordsColor = highlighting.GetNamedColor("AttributeKeywords"); |
||||
//this.externAliasKeywordColor = ...;
|
||||
} |
||||
|
||||
public override void WriteKeyword(Role role, string keyword) |
||||
{ |
||||
HighlightingColor color = null; |
||||
switch (keyword) { |
||||
case "namespace": |
||||
case "using": |
||||
if (role == UsingStatement.UsingKeywordRole) |
||||
color = structureKeywordsColor; |
||||
else |
||||
color = namespaceKeywordsColor; |
||||
break; |
||||
case "this": |
||||
case "base": |
||||
color = thisKeywordColor; |
||||
break; |
||||
case "true": |
||||
case "false": |
||||
color = trueKeywordColor; |
||||
break; |
||||
case "public": |
||||
case "internal": |
||||
case "protected": |
||||
case "private": |
||||
color = visibilityKeywordsColor; |
||||
break; |
||||
case "if": |
||||
case "else": |
||||
case "switch": |
||||
case "case": |
||||
case "default": |
||||
case "while": |
||||
case "do": |
||||
case "for": |
||||
case "foreach": |
||||
case "lock": |
||||
case "global": |
||||
case "dynamic": |
||||
case "await": |
||||
case "where": |
||||
color = structureKeywordsColor; |
||||
break; |
||||
case "in": |
||||
if (nodeStack.PeekOrDefault() is ForeachStatement) |
||||
color = structureKeywordsColor; |
||||
else if (nodeStack.PeekOrDefault() is QueryClause) |
||||
color = queryKeywordsColor; |
||||
else |
||||
color = parameterModifierColor; |
||||
break; |
||||
case "as": |
||||
case "is": |
||||
case "new": |
||||
case "sizeof": |
||||
case "typeof": |
||||
case "nameof": |
||||
case "stackalloc": |
||||
color = typeKeywordsColor; |
||||
break; |
||||
case "try": |
||||
case "throw": |
||||
case "catch": |
||||
case "finally": |
||||
color = exceptionKeywordsColor; |
||||
break; |
||||
case "when": |
||||
if (role == CatchClause.WhenKeywordRole) |
||||
color = exceptionKeywordsColor; |
||||
break; |
||||
case "get": |
||||
case "set": |
||||
case "add": |
||||
case "remove": |
||||
if (role == PropertyDeclaration.GetKeywordRole || |
||||
role == PropertyDeclaration.SetKeywordRole || |
||||
role == CustomEventDeclaration.AddKeywordRole || |
||||
role == CustomEventDeclaration.RemoveKeywordRole) |
||||
color = accessorKeywordsColor; |
||||
break; |
||||
case "abstract": |
||||
case "const": |
||||
case "event": |
||||
case "extern": |
||||
case "override": |
||||
case "readonly": |
||||
case "sealed": |
||||
case "static": |
||||
case "virtual": |
||||
case "volatile": |
||||
case "async": |
||||
case "partial": |
||||
color = modifiersColor; |
||||
break; |
||||
case "checked": |
||||
case "unchecked": |
||||
color = checkedKeywordColor; |
||||
break; |
||||
case "fixed": |
||||
case "unsafe": |
||||
color = unsafeKeywordsColor; |
||||
break; |
||||
case "enum": |
||||
case "struct": |
||||
color = valueTypeKeywordsColor; |
||||
break; |
||||
case "class": |
||||
case "interface": |
||||
case "delegate": |
||||
color = referenceTypeKeywordsColor; |
||||
break; |
||||
case "select": |
||||
case "group": |
||||
case "by": |
||||
case "into": |
||||
case "from": |
||||
case "ascending": |
||||
case "descending": |
||||
case "orderby": |
||||
case "let": |
||||
case "join": |
||||
case "on": |
||||
case "equals": |
||||
if (nodeStack.PeekOrDefault() is QueryClause) |
||||
color = queryKeywordsColor; |
||||
break; |
||||
case "explicit": |
||||
case "implicit": |
||||
case "operator": |
||||
color = operatorKeywordsColor; |
||||
break; |
||||
case "params": |
||||
case "ref": |
||||
case "out": |
||||
color = parameterModifierColor; |
||||
break; |
||||
case "break": |
||||
case "continue": |
||||
case "goto": |
||||
case "yield": |
||||
case "return": |
||||
color = gotoKeywordsColor; |
||||
break; |
||||
} |
||||
if (nodeStack.PeekOrDefault() is AttributeSection) |
||||
color = attributeKeywordsColor; |
||||
if (color != null) { |
||||
textOutput.BeginSpan(color); |
||||
} |
||||
base.WriteKeyword(role, keyword); |
||||
if (color != null) { |
||||
textOutput.EndSpan(); |
||||
} |
||||
} |
||||
|
||||
public override void WritePrimitiveType(string type) |
||||
{ |
||||
HighlightingColor color = null; |
||||
switch (type) { |
||||
case "new": |
||||
color = typeKeywordsColor; |
||||
break; |
||||
case "bool": |
||||
case "byte": |
||||
case "char": |
||||
case "decimal": |
||||
case "double": |
||||
case "enum": |
||||
case "float": |
||||
case "int": |
||||
case "long": |
||||
case "sbyte": |
||||
case "short": |
||||
case "struct": |
||||
case "uint": |
||||
case "ushort": |
||||
case "ulong": |
||||
color = valueTypeKeywordsColor; |
||||
break; |
||||
case "object": |
||||
case "string": |
||||
case "void": |
||||
color = referenceTypeKeywordsColor; |
||||
break; |
||||
} |
||||
if (color != null) { |
||||
textOutput.BeginSpan(color); |
||||
} |
||||
base.WritePrimitiveType(type); |
||||
if (color != null) { |
||||
textOutput.EndSpan(); |
||||
} |
||||
} |
||||
|
||||
public override void WriteIdentifier(Identifier identifier) |
||||
{ |
||||
HighlightingColor color = null; |
||||
if (identifier.Name == "value" && nodeStack.PeekOrDefault() is Accessor accessor && accessor.Role != PropertyDeclaration.GetterRole) |
||||
color = valueKeywordColor; |
||||
switch (GetCurrentDefinition()) { |
||||
case ITypeDefinition t: |
||||
switch (t.Kind) { |
||||
case TypeKind.Delegate: |
||||
color = delegateTypeColor; |
||||
break; |
||||
case TypeKind.Class: |
||||
color = referenceTypeColor; |
||||
break; |
||||
case TypeKind.Interface: |
||||
color = interfaceTypeColor; |
||||
break; |
||||
case TypeKind.Enum: |
||||
color = enumerationTypeColor; |
||||
break; |
||||
case TypeKind.Struct: |
||||
color = valueTypeColor; |
||||
break; |
||||
} |
||||
break; |
||||
case IMethod m: |
||||
color = methodDeclarationColor; |
||||
break; |
||||
case IField f: |
||||
color = fieldDeclarationColor; |
||||
break; |
||||
} |
||||
switch (GetCurrentMemberReference()) { |
||||
case IType t: |
||||
switch (t.Kind) { |
||||
case TypeKind.Delegate: |
||||
color = delegateTypeColor; |
||||
break; |
||||
case TypeKind.Class: |
||||
color = referenceTypeColor; |
||||
break; |
||||
case TypeKind.Interface: |
||||
color = interfaceTypeColor; |
||||
break; |
||||
case TypeKind.Enum: |
||||
color = enumerationTypeColor; |
||||
break; |
||||
case TypeKind.Struct: |
||||
color = valueTypeColor; |
||||
break; |
||||
} |
||||
break; |
||||
case IMethod m: |
||||
color = methodCallColor; |
||||
break; |
||||
case IField f: |
||||
color = fieldAccessColor; |
||||
break; |
||||
} |
||||
if (color != null) { |
||||
textOutput.BeginSpan(color); |
||||
} |
||||
base.WriteIdentifier(identifier); |
||||
if (color != null) { |
||||
textOutput.EndSpan(); |
||||
} |
||||
} |
||||
|
||||
public override void WritePrimitiveValue(object value, string literalValue = null) |
||||
{ |
||||
HighlightingColor color = null; |
||||
if (value is null) { |
||||
color = valueKeywordColor; |
||||
} |
||||
if (value is true || value is false) { |
||||
color = trueKeywordColor; |
||||
} |
||||
if (color != null) { |
||||
textOutput.BeginSpan(color); |
||||
} |
||||
base.WritePrimitiveValue(value, literalValue); |
||||
if (color != null) { |
||||
textOutput.EndSpan(); |
||||
} |
||||
} |
||||
|
||||
ISymbol GetCurrentDefinition() |
||||
{ |
||||
if (nodeStack == null || nodeStack.Count == 0) |
||||
return null; |
||||
|
||||
var node = nodeStack.Peek(); |
||||
if (node is Identifier) |
||||
node = node.Parent; |
||||
if (IsDefinition(ref node)) |
||||
return node.GetSymbol(); |
||||
|
||||
return null; |
||||
} |
||||
|
||||
static bool IsDefinition(ref AstNode node) |
||||
{ |
||||
if (node is EntityDeclaration) |
||||
return true; |
||||
if (node is VariableInitializer && node.Parent is FieldDeclaration) { |
||||
node = node.Parent; |
||||
return true; |
||||
} |
||||
if (node is FixedVariableInitializer) |
||||
return true; |
||||
return false; |
||||
} |
||||
|
||||
ISymbol GetCurrentMemberReference() |
||||
{ |
||||
AstNode node = nodeStack.Peek(); |
||||
var symbol = node.GetSymbol(); |
||||
if (symbol == null && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) { |
||||
symbol = node.Parent.GetSymbol(); |
||||
} |
||||
if (symbol != null && node.Parent is ObjectCreateExpression) { |
||||
symbol = node.Parent.GetSymbol(); |
||||
} |
||||
if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) { |
||||
var declaringType = member.DeclaringType; |
||||
if (declaringType != null && declaringType.Kind == TypeKind.Delegate) |
||||
return null; |
||||
} |
||||
return symbol; |
||||
} |
||||
|
||||
Stack<AstNode> nodeStack = new Stack<AstNode>(); |
||||
|
||||
public override void StartNode(AstNode node) |
||||
{ |
||||
nodeStack.Push(node); |
||||
base.StartNode(node); |
||||
} |
||||
|
||||
public override void EndNode(AstNode node) |
||||
{ |
||||
base.EndNode(node); |
||||
nodeStack.Pop(); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue