Browse Source

Use SemanticHighlightingVisitor in CSharpSemanticHighlighter.

pull/32/merge
Daniel Grunwald 13 years ago
parent
commit
e51750a232
  1. 291
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs
  2. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/SemanticHighlightingVisitor.cs

291
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs

@ -5,39 +5,25 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Windows.Threading;
using CSharpBinding.Parser;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using CSharpBinding.Parser;
namespace CSharpBinding namespace CSharpBinding
{ {
/// <summary> /// <summary>
/// Semantic highlighting for C#. /// Semantic highlighting for C#.
/// </summary> /// </summary>
public class CSharpSemanticHighlighter : DepthFirstAstVisitor, IHighlighter public class CSharpSemanticHighlighter : SemanticHighlightingVisitor<HighlightingColor>, IHighlighter
{ {
readonly IDocument document; readonly IDocument document;
readonly HighlightingColor defaultTextColor;
readonly HighlightingColor referenceTypeColor;
readonly HighlightingColor valueTypeColor;
readonly HighlightingColor methodCallColor;
readonly HighlightingColor fieldAccessColor;
readonly HighlightingColor valueKeywordColor;
readonly HighlightingColor parameterModifierColor;
readonly HighlightingColor inactiveCodeColor;
List<IDocumentLine> invalidLines; List<IDocumentLine> invalidLines;
List<CachedLine> cachedLines; List<CachedLine> cachedLines;
@ -48,11 +34,8 @@ namespace CSharpBinding
int lineNumber; int lineNumber;
HighlightedLine line; HighlightedLine line;
CSharpAstResolver resolver;
CSharpFullParseInformation parseInfo; CSharpFullParseInformation parseInfo;
bool isInAccessor;
#region Constructor + Dispose #region Constructor + Dispose
public CSharpSemanticHighlighter(IDocument document) public CSharpSemanticHighlighter(IDocument document)
{ {
@ -61,7 +44,7 @@ namespace CSharpBinding
this.document = document; this.document = document;
var highlighting = HighlightingManager.Instance.GetDefinition("C#"); var highlighting = HighlightingManager.Instance.GetDefinition("C#");
this.defaultTextColor = highlighting.GetNamedColor("DefaultTextAndBackground"); //this.defaultTextColor = ???;
this.referenceTypeColor = highlighting.GetNamedColor("ReferenceTypes"); this.referenceTypeColor = highlighting.GetNamedColor("ReferenceTypes");
this.valueTypeColor = highlighting.GetNamedColor("ValueTypes"); this.valueTypeColor = highlighting.GetNamedColor("ValueTypes");
this.methodCallColor = highlighting.GetNamedColor("MethodCall"); this.methodCallColor = highlighting.GetNamedColor("MethodCall");
@ -281,6 +264,8 @@ namespace CSharpBinding
line = new HighlightedLine(document, documentLine); line = new HighlightedLine(document, documentLine);
this.lineNumber = lineNumber; this.lineNumber = lineNumber;
this.regionStart = new TextLocation(lineNumber, 1);
this.regionEnd = new TextLocation(lineNumber, 1 + document.GetLineByNumber(lineNumber).Length);
if (Debugger.IsAttached) { if (Debugger.IsAttached) {
parseInfo.SyntaxTree.AcceptVisitor(this); parseInfo.SyntaxTree.AcceptVisitor(this);
} else { } else {
@ -298,9 +283,9 @@ namespace CSharpBinding
return line; return line;
} }
public HighlightingColor DefaultTextColor { HighlightingColor IHighlighter.DefaultTextColor {
get { get {
return defaultTextColor; return null;
} }
} }
@ -333,30 +318,7 @@ namespace CSharpBinding
#endregion #endregion
#region Colorize #region Colorize
HighlightingColor GetColor(ResolveResult rr) protected override void Colorize(TextLocation start, TextLocation end, HighlightingColor color)
{
if (rr is TypeResolveResult) {
if (rr.Type.IsReferenceType == false)
return valueTypeColor;
else
return referenceTypeColor;
}
MemberResolveResult mrr = rr as MemberResolveResult;
if (mrr != null) {
if (mrr.Member is IField)
return fieldAccessColor;
}
return null;
}
void Colorize(AstNode node, HighlightingColor color)
{
if (node.IsNull || color == null)
return;
Colorize(node.StartLocation, node.EndLocation, color);
}
void Colorize(TextLocation start, TextLocation end, HighlightingColor color)
{ {
if (color == null) if (color == null)
return; return;
@ -377,240 +339,5 @@ namespace CSharpBinding
} }
} }
#endregion #endregion
#region AST Traversal
protected override void VisitChildren(AstNode node)
{
for (var child = node.FirstChild; child != null; child = child.NextSibling) {
if (child.StartLocation.Line <= lineNumber && child.EndLocation.Line >= lineNumber)
child.AcceptVisitor(this);
}
}
public override void VisitSimpleType(SimpleType simpleType)
{
Colorize(simpleType.IdentifierToken, GetColor(resolver.Resolve(simpleType)));
simpleType.TypeArguments.AcceptVisitor(this);
}
public override void VisitMemberType(MemberType memberType)
{
// Ensure we visit/colorize the children in the correct order.
// This is required so that the resulting HighlightedSections are sorted correctly.
memberType.Target.AcceptVisitor(this);
Colorize(memberType.MemberNameToken, GetColor(resolver.Resolve(memberType)));
memberType.TypeArguments.AcceptVisitor(this);
}
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{
Identifier ident = identifierExpression.GetChildByRole(Roles.Identifier);
if (isInAccessor && identifierExpression.Identifier == "value") {
Colorize(ident, valueKeywordColor);
} else {
ResolveResult rr = resolver.Resolve(identifierExpression);
Colorize(ident, GetColor(rr));
}
identifierExpression.TypeArguments.AcceptVisitor(this);
}
public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
{
memberReferenceExpression.Target.AcceptVisitor(this);
ResolveResult rr = resolver.Resolve(memberReferenceExpression);
Colorize(memberReferenceExpression.MemberNameToken, GetColor(rr));
memberReferenceExpression.TypeArguments.AcceptVisitor(this);
}
public override void VisitInvocationExpression(InvocationExpression invocationExpression)
{
Expression target = invocationExpression.Target;
if (target is IdentifierExpression || target is MemberReferenceExpression || target is PointerReferenceExpression) {
var invocationRR = resolver.Resolve(invocationExpression) as CSharpInvocationResolveResult;
if (invocationRR != null && IsInactiveConditionalMethod(invocationRR.Member)) {
// mark the whole invocation expression as inactive code
Colorize(invocationExpression, inactiveCodeColor);
return;
}
// apply color to target's target
target.GetChildByRole(Roles.TargetExpression).AcceptVisitor(this);
// highlight the method call
var identifier = target.GetChildByRole(Roles.Identifier);
if (invocationRR != null && !invocationRR.IsDelegateInvocation) {
Colorize(identifier, methodCallColor);
} else {
ResolveResult targetRR = resolver.Resolve(target);
Colorize(identifier, GetColor(targetRR));
}
target.GetChildrenByRole(Roles.TypeArgument).AcceptVisitor(this);
} else {
target.AcceptVisitor(this);
}
// Visit arguments and comments within the arguments:
for (AstNode child = target.NextSibling; child != null; child = child.NextSibling) {
child.AcceptVisitor(this);
}
}
bool IsInactiveConditionalMethod(IParameterizedMember member)
{
if (member.EntityType != EntityType.Method || member.ReturnType.Kind != TypeKind.Void)
return false;
while (member.IsOverride)
member = (IParameterizedMember)InheritanceHelper.GetBaseMember(member);
return IsInactiveConditional(member.Attributes);
}
bool IsInactiveConditional(IList<IAttribute> attributes)
{
bool hasConditionalAttribute = false;
foreach (var attr in attributes) {
if (attr.AttributeType.Name == "ConditionalAttribute" && attr.AttributeType.Namespace == "System.Diagnostics" && attr.PositionalArguments.Count == 1) {
string symbol = attr.PositionalArguments[0].ConstantValue as string;
if (symbol != null) {
hasConditionalAttribute = true;
var cu = this.resolver.RootNode as SyntaxTree;
if (cu != null) {
if (cu.ConditionalSymbols.Contains(symbol))
return false; // conditional is active
}
}
}
}
return hasConditionalAttribute;
}
public override void VisitAccessor(Accessor accessor)
{
isInAccessor = true;
try {
base.VisitAccessor(accessor);
} finally {
isInAccessor = false;
}
}
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
for (AstNode child = methodDeclaration.FirstChild; child != null; child = child.NextSibling) {
if (child.StartLocation.Line <= lineNumber && child.EndLocation.Line >= lineNumber) {
if (child.Role == Roles.Identifier) {
// child == methodDeclaration.NameToken
Colorize(child, methodCallColor);
} else {
child.AcceptVisitor(this);
}
}
}
}
public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{
HandleConstructorOrDestructor(constructorDeclaration);
}
public override void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
{
HandleConstructorOrDestructor(destructorDeclaration);
}
void HandleConstructorOrDestructor(AstNode constructorDeclaration)
{
for (AstNode child = constructorDeclaration.FirstChild; child != null; child = child.NextSibling) {
if (child.StartLocation.Line <= lineNumber && child.EndLocation.Line >= lineNumber) {
if (child.Role == Roles.Identifier) {
// child == constructorDeclaration.NameToken
var currentTypeDef = resolver.GetResolverStateBefore(constructorDeclaration).CurrentTypeDefinition;
if (currentTypeDef != null && ((Identifier)child).Name == currentTypeDef.Name) {
if (currentTypeDef.IsReferenceType == true)
Colorize(child, referenceTypeColor);
else if (currentTypeDef.IsReferenceType == false)
Colorize(child, valueTypeColor);
}
} else {
child.AcceptVisitor(this);
}
}
}
}
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
// Type declarations often contain #if directives, so we must make sure
// to also visit the comments.
for (AstNode child = typeDeclaration.FirstChild; child != null; child = child.NextSibling) {
if (child.StartLocation.Line <= lineNumber && child.EndLocation.Line >= lineNumber) {
if (child.Role == Roles.Identifier) {
// child == typeDeclaration.NameToken
if (typeDeclaration.ClassType == ClassType.Enum || typeDeclaration.ClassType == ClassType.Struct)
Colorize(typeDeclaration.NameToken, valueTypeColor);
else
Colorize(typeDeclaration.NameToken, referenceTypeColor);
} else {
child.AcceptVisitor(this);
}
}
}
}
public override void VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
{
typeParameterDeclaration.Attributes.AcceptVisitor(this);
if (typeParameterDeclaration.Variance == VarianceModifier.Contravariant)
Colorize(typeParameterDeclaration.VarianceToken, parameterModifierColor);
bool isValueType = false;
if (typeParameterDeclaration.Parent != null) {
foreach (var constraint in typeParameterDeclaration.Parent.GetChildrenByRole(Roles.Constraint)) {
if (constraint.TypeParameter.Identifier == typeParameterDeclaration.Name) {
isValueType = constraint.BaseTypes.OfType<PrimitiveType>().Any(p => p.Keyword == "struct");
}
}
}
Colorize(typeParameterDeclaration.NameToken, isValueType ? valueTypeColor : referenceTypeColor);
}
public override void VisitConstraint(Constraint constraint)
{
if (constraint.Parent != null && constraint.Parent.GetChildrenByRole(Roles.TypeParameter).Any(tp => tp.Name == constraint.TypeParameter.Identifier)) {
bool isValueType = constraint.BaseTypes.OfType<PrimitiveType>().Any(p => p.Keyword == "struct");
Colorize(constraint.GetChildByRole(Roles.Identifier), isValueType ? valueTypeColor : referenceTypeColor);
}
constraint.BaseTypes.AcceptVisitor(this);
}
public override void VisitVariableInitializer(VariableInitializer variableInitializer)
{
if (variableInitializer.Parent is FieldDeclaration) {
Colorize(variableInitializer.NameToken, fieldAccessColor);
}
variableInitializer.Initializer.AcceptVisitor(this);
}
public override void VisitComment(Comment comment)
{
if (comment.CommentType == CommentType.InactiveCode) {
Colorize(comment, inactiveCodeColor);
}
}
public override void VisitAttribute(ICSharpCode.NRefactory.CSharp.Attribute attribute)
{
ITypeDefinition attrDef = resolver.Resolve(attribute.Type).Type.GetDefinition();
if (attrDef != null && IsInactiveConditional(attrDef.Attributes)) {
Colorize(attribute, inactiveCodeColor);
return;
}
VisitChildren(attribute);
}
#endregion
} }
} }

1
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/SemanticHighlightingVisitor.cs

@ -201,7 +201,6 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
VisitChildrenUntil(memberReferenceExpression, memberNameToken); VisitChildrenUntil(memberReferenceExpression, memberNameToken);
ResolveResult rr = resolver.Resolve(memberReferenceExpression); ResolveResult rr = resolver.Resolve(memberReferenceExpression);
Colorize(memberNameToken, rr); Colorize(memberNameToken, rr);
VisitChildren(memberReferenceExpression);
VisitChildrenAfter(memberReferenceExpression, memberNameToken); VisitChildrenAfter(memberReferenceExpression, memberNameToken);
} }

Loading…
Cancel
Save