Adding syntax highlighting rules to AvalonEdit programmatically - syntax-highlighting

I'm using AvalonEdit in an app that runs my own custom-built language. I want to put in appropriate syntax highlighting into Avalon Edit. Normally this is done by defining the highlighting rules in an xml file by hand.
However, I don't want the highlighting rules to always be falling out of sync with the language grammar whenever I extend the language. So I'm hoping to use the grammar info that's already contained in my coco/R parser to automatically generate these rules.
So is there a way to programmatically add syntax highlighting rules to Avalon Edit?
Thanks

The below code worked for me at least.
Assembly assembly = Assembly.GetExecutingAssembly();
using (Stream s = assembly.GetManifestResourceStream("Your.xshd"))
{
using (XmlTextReader reader = new XmlTextReader(s))
{
//Load default Syntax Highlighting
InternalEditor.SyntaxHighlighting = HighlightingLoader.Load(reader, HighlightingManager.Instance);
// Dynamic syntax highlighting for your own purpose
var rules = InternalEditor.SyntaxHighlighting.MainRuleSet.Rules;
_HighlightingRule = new HighlightingRule();
_HighlightingRule.Color = new HighlightingColor()
{
Foreground = new CustomizedBrush(SomeColor)
};
String[] wordList = PseudoGetKeywords(); // Your own logic
String regex = String.Format(#"\b({0})\w*\b", String.Join("|", wordList));
_HighlightingRule.Regex = new Regex(regex);
rules.Add(_HighlightingRule);
}
}
internal sealed class CustomizedBrush : HighlightingBrush
{
private readonly SolidColorBrush brush;
public CustomizedBrush(Color color)
{
brush = CreateFrozenBrush(color);
}
public CustomizedBrush(System.Drawing.Color c)
{
var c2 = System.Windows.Media.Color.FromArgb(c.A, c.R, c.G, c.B);
brush = CreateFrozenBrush(c2);
}
public override Brush GetBrush(ITextRunConstructionContext context)
{
return brush;
}
public override string ToString()
{
return brush.ToString();
}
private static SolidColorBrush CreateFrozenBrush(Color color)
{
SolidColorBrush brush = new SolidColorBrush(color);
brush.Freeze();
return brush;
}
}

You can generate an .xshd file in memory using the object model in ICSharpCode.AvalonEdit.Highlighting.Xshd (XshdSyntaxDefinition etc.).
To convert it into an IHighlightingDefinition, use the HighlightingLoader.Load() method. You can also save it to disk (for debugging purposes) by applying the SaveXshdVisitor.
Alternatively, you could implement IHighlightingDefinition yourself and directly create HighlightingRuleSet instances.

Related

Roslyn analyser: Nullable annotations in Linq

I am brand new to Roslyn and I have to write an analyser that will aid in improving nullable annotations when using Linq. The goal is to force any usages of .XYZOrDefault() to be stored in a nullable type variable/property/method signature. For example: if we use "var x = SomeKindOfList.FirstOrDefault()", "x" needs to be marked as nullable. We will be using C# 8, so I'm referring to NRTs. The idea of achieving this is by:
Determining if generic types are being used in the variable or
method declaration
Use semantic model to determine if the left hand
side of the expression's type is a nullable type
If left hand side of expression is not a nullable type, produce a
diagnostic
I've gotten this far with my coding:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
Compilation compilation = context.Compilation;
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
// Find implicitly typed variable declarations.
if (declaration.Type.IsVar)
{
foreach (var variable in declaration.Variables)
{
var variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
var invocationSymbol = context.SemanticModel.GetOperation(variable.Initializer.Value).Type;
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variableSymbol.Locations[0], variableSymbol.Name);
context.ReportDiagnostic(diagnostic);
}
}
}
}
I've read so much about what you can do that at this stage it's an information overload. Any articles, code snippets or advise that can just give me some more direction would be highly appreciated!
In the end we ended up writing our own analyzer as an interim solution until we can move to .Net 5. The most basic implementation that we came up with was the following code:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
foreach (var variable in declaration.Variables)
{
ITypeSymbol? variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
IOperation? invocationOperationInfo = context.SemanticModel.GetOperation(variable.Initializer.Value);
if (invocationOperationInfo is IInvocationOperation op)
{
if (op.TargetMethod.IsGenericMethod)
{
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variable.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
}
}
}
}
Hope this can help someone else who is, perhaps, just looking for a good starting point when having to develop something similar.

Change the scalar style used for all multi-line strings when serialising a dynamic model using YamlDotNet

I am using the following code snippet to serialise a dynamic model of a project to a string (which is eventually exported to a YAML file).
dynamic exportModel = exportModelConvertor.ToDynamicModel(project);
var serializerBuilder = new SerializerBuilder();
var serializer = serializerBuilder.EmitDefaults().DisableAliases().Build();
using (var sw = new StringWriter())
{
serializer.Serialize(sw, exportModel);
string result = sw.ToString();
}
Any multi-line strings such as the following:
propertyName = "One line of text
followed by another line
and another line"
are exported in the following format:
propertyName: >
One line of text
followed by another line
and another line
Note the extra (unwanted) line breaks.
According to this YAML Multiline guide, the format used here is the folded block scalar style. Is there a way using YamlDotNet to change the style of this output for all multi-line string properties to literal block scalar style or one of the flow scalar styles?
The YamlDotNet documentation shows how to apply ScalarStyle.DoubleQuoted to a particular property using WithAttributeOverride but this requires a class name and the model to be serialised is dynamic. This also requires listing every property to change (of which there are many). I would like to change the style for all multi-line string properties at once.
To answer my own question, I've now worked out how to do this by deriving from the ChainedEventEmitter class and overriding void Emit(ScalarEventInfo eventInfo, IEmitter emitter). See code sample below.
public class MultilineScalarFlowStyleEmitter : ChainedEventEmitter
{
public MultilineScalarFlowStyleEmitter(IEventEmitter nextEmitter)
: base(nextEmitter) { }
public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter)
{
if (typeof(string).IsAssignableFrom(eventInfo.Source.Type))
{
string value = eventInfo.Source.Value as string;
if (!string.IsNullOrEmpty(value))
{
bool isMultiLine = value.IndexOfAny(new char[] { '\r', '\n', '\x85', '\x2028', '\x2029' }) >= 0;
if (isMultiLine)
eventInfo = new ScalarEventInfo(eventInfo.Source)
{
Style = ScalarStyle.Literal
};
}
}
nextEmitter.Emit(eventInfo, emitter);
}
}

Adobe AIR Scrolling Performance on iPad (2) - What Can I Expect?

I'm currently working on an Adobe AIR application which is targeting the iPad2 as the hardware platform, and can not get decent scrolling performance on one of the screens. I'm using a spark list, with a custom item renderer like so:
<s:List id="productList" top="116" bottom="0" left="10" right="10"
width="100%"
visible="true" includeInLayout="true"
height="0"
maxHeight="500"
opaqueBackground="#ffffff"
itemRenderer="myRenderer">
</s:List>
Originally, I was using an .mxml renderer, but after seeing the nasty performance I decided to roll my own, extending UIComponent (I've left off the package and braces to save on horizontal space):
import mx.controls.listClasses.IListItemRenderer;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.utils.ColorUtil;
import spark.components.Label;
import spark.components.TextInput;
public final class OrderViewProductLineTestIR extends UIComponent implements IListItemRenderer
{
public function OrderViewProductLineTestIR()
{
super();
}
// Internal variable for the property value.
private var _data:Object;
private var productName:Label;
private var orderQty:TextInput;
private var stockQty:TextInput;
// Make the data property bindable.
[Bindable("dataChange")]
// Define the getter method.
public function get data():Object
{
return _data;
}
// Define the setter method, and dispatch an event when the property
// changes to support data binding.
public function set data(value:Object):void
{
_data = value;
invalidateProperties();
dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}
override protected function createChildren():void
{
super.createChildren();
productName = new Label();
// productName.visible = true;
addChild(productName);
orderQty = new TextInput();
addChild(orderQty);
stockQty = new TextInput();
addChild(stockQty);
}
override protected function commitProperties():void
{
super.commitProperties();
productName.text = _data.Name;
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
productName.move(0, 0);
productName.setActualSize(250, 48);
orderQty.move(270, 0);
orderQty.setActualSize(100, 48);
stockQty.move(390, 0);
stockQty.setActualSize(100, 48);
}
override protected function measure():void
{
super.measure();
measuredWidth = 490;
measuredHeight = 48;
}
}
As you can see this is pretty light-weight, yet my dataprovider contains upwards of 100 items, and 11 of them can be on screen at any one time. Everything I've read around increasing performance for scrolling revolves around using opaqueBackground and cacheAsBitmap, however no matter what I try neither help here. Using cacheAsBitmap at the list level doesn't help as the item renderer recycling kicks in once you've scrolled more than a couple of lines requiring the whole thing to be re-rendered, and using it at the item renderer level is still horribly slow when scrolling fast — presumably because many are being recycled at once during a very fast scroll.
I know the iPad should have no problem blitting a screenful of information in a frame at 60 fps, yet when I scroll quickly I'm seeing it struggle to make 10 fps (from sight). So the question: have I missed something obvious, or is this to be expected due to the number of layers (and vector rendering) involved when using AIR? For the record, I have tried changing the render mode for the application and tried changing the frame rate to eliminate the obvious.
This is a bit of guessing, but can the itemRenderer be optimized? Do all the children need to be positioned and sized every time component redraws? Do you need to update productName.text every time commitProperties run?
Here is how I might modify things:
import mx.controls.listClasses.IListItemRenderer;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.utils.ColorUtil;
import spark.components.Label;
import spark.components.TextInput;
public final class OrderViewProductLineTestIR extends UIComponent implements IListItemRenderer
{
public function OrderViewProductLineTestIR()
{
super();
}
// Internal variable for the property value.
private var _data:Object;
// Add a dataChanged property
private var dataChanged :Boolean = false
private var productName:Label;
private var orderQty:TextInput;
private var stockQty:TextInput;
// Make the data property bindable.
[Bindable("dataChange")]
// Define the getter method.
public function get data():Object
{
return _data;
}
// Define the setter method, and dispatch an event when the property
// changes to support data binding.
public function set data(value:Object):void
{
_data = value;
// switch the dataChanged flag
dataChanged = true;
invalidateProperties();
dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}
override protected function createChildren():void
{
super.createChildren();
productName = new Label();
// productName.visible = true;
addChild(productName);
orderQty = new TextInput();
addChild(orderQty);
stockQty = new TextInput();
addChild(stockQty);
}
override protected function commitProperties():void
{
super.commitProperties();
// Only update the display if the data actually changed
If(dataChanged){
productName.text = _data.Name;
dataChanged = false;
}
}
// add variable to tell whether the component's children have been sized and positioned or not
// since they have static locations, no need to set these each time
protected var compChildrenSized :Boolean = false;
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(!compChildrenSized){
productName.move(0, 0);
productName.setActualSize(250, 48);
orderQty.move(270, 0);
orderQty.setActualSize(100, 48);
stockQty.move(390, 0);
stockQty.setActualSize(100, 48);
compChildrenSized = true;
}
}
override protected function measure():void
{
super.measure();
measuredWidth = 490;
measuredHeight = 48;
}
}
I guess I'll add that I'm not sure measure will ever run. What happens if you replace the textInputs with labels? Are you using Flex 4.6, and if so are you using StyleableStageText (AKA StageText) or the 4.5 skin which uses StyleableTextField? I wonder if StageText scrolling could kill performance because it hangs out above the Flash Display list.
What happens if you remove the textInput completely and replace with labels?
These are little things, and I'm not sure if they'll help.
Try just this on your "Spark List component"
1/ add a layout (horizontal or vertical depending on what you want ;)
2/ add attribute "useVirtualLayout=true" on your list component !
And tell me what's the result ... but i think it will be smoother (very very smoother),
because when you add your elements to the list, all the components are rendered, even if
they are out of the layout ... so whith "useVirtualLayout" just items that are on the viewport are rendered others are destroyed ...
See ya ! and have fun whith Flash Builder ! it's a so cool technology to have a multi support app !
A bit late. but.
Its true that its better to use starling and feather if you want something close to native performance.
But you can still optimise your renderer.
Please dont use binding anywhere in a Flex mobile application.
Extending UIComponent is the right thing to do.
I think it would be better to not use invalidation and set your properties in the data setter.
Hope it helps.

Debugger Visualizer [Visual Studio 2010] - System.Linq.Expressions.Expression - not showing magnifying glass

I have been trying to build a debugger visualizer for a linq Expression.
I know one exists already, but I would like to create my own and add additional functionality.
I made this quick prototype.
The magnifying glass will not show up; however, if I change the one line of code to "Target = typeof(System.String)", the magnifying glass shows up.
Any help would be appreciated.
using System.IO;
using System.Windows.Forms;
using Microsoft.VisualStudio.DebuggerVisualizers;
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(VisualizerPrototype.MyDebuggerVisualizer),
typeof(VisualizerPrototype.MyDebuggerVisualizerObjectSource),
Target = typeof(System.Linq.Expressions.Expression),
Description = "My Debugger Visualizer")]
namespace VisualizerPrototype
{
public class MyDebuggerVisualizer : DialogDebuggerVisualizer
{
protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
var text = string.Empty;
using (var sr = new StreamReader(objectProvider.GetData()))
{
text = sr.ReadToEnd();
}
MessageBox.Show(text);
}
}
public class MyDebuggerVisualizerObjectSource : VisualizerObjectSource
{
public override void GetData(object target, System.IO.Stream outgoingData)
{
var sw = new StreamWriter(outgoingData);
sw.WriteLine("YO");
sw.Flush();
}
}
}
For anybody reading this in the future, I discovered the source of my problem.
The target type for a debugger visualizer must be the runtime type and not an inherited type.
Target = typeof(System.Linq.Expressions.ConstantExpression)
Expression expr = Expression.Constant(1); //visualizer shows up
Target = typeof(System.Linq.Expressions.Expression)
Expression expr = Expression.Constant(1); //visualizer doesn't show up
Try this one for VB:
Target = GetType(Expression(Of ))
Or this one for C#:
Target = typeof(Expression<>)

Using LINQ, how do you get all label controls

I want to get a collection of all label controls that are part of a user control. I have the following code:
var labelControls = from Control ctl in this.Controls
where ctl.GetType() == typeof(Label)
select ctl;
but the result is zero results.
Please assist. Thanks.
Edit
I have also tried the following code without success.
this.Controls
.OfType<Label>()
.Where(ctl => ctl.ID.Contains("myPrefix"))
.ToList()
.ForEach(lbl => lbl.ForeColor = System.Drawing.Color.Black);
Again, without success.
Are you sure that the control whose child controls you are parsing actually directly contains Label controls? I suspect that it is a child of the main control that is hosting the labels, in which case, you need to recursively search through the UI tree to find the labels.
Something like:
public static IEnumerable<Label> DescendantLabels(this Control control)
{
return control.Controls.DescendantLabels();
}
public static IEnumerable<Label> DescendantLabels(this ControlCollection controls)
{
var childControls = controls.OfType<Label>();
foreach (Control control in controls)
{
childControls = childControls.Concat(control.DescendantLabels());
}
return childControls;
}
Controls.OfType<Label>() - thats all
For nested controls
public static class ext
{
public static List<Label> GetLabels(this Control control)
{
var chList = control.Controls.OfType<Label>().ToList();
chList.AddRange(((IEnumerable<Control>)control.Controls)
.SelectMany(c => c.GetLabels()));
return chList;
}
}
var labelControls = this.Controls.OfType<Label>();

Resources