I'm trying to create a classifier VS extension to colorize "TODO" comments. For that, in my IClassifier.GetClassificationSpans method I want to get the current classification spans, and only process those classified as "comment".
In my classifier provider I added an IClassifierAggregatorService field, and used its GetClassifier method to pass the result to my classifier, which can use it to get the classifications. However, this generates a StackOverflowException, since my GetClassifier method is called again and again in a loop:
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
namespace TestTasksClassifier
{
[Export(typeof(IClassifierProvider))]
[ContentType("code")]
internal class EditorClassifier1Provider : IClassifierProvider
{
[Import] private IClassificationTypeRegistryService classificationRegistry;
[Import] private IClassifierAggregatorService aggregatorService;
public IClassifier GetClassifier(ITextBuffer buffer)
{
return buffer.Properties.GetOrCreateSingletonProperty<EditorClassifier1>(creator: () =>
new EditorClassifier1(classificationRegistry, aggregatorService.GetClassifier(buffer)));
}
}
}
To solve the StackOverflowException, in GetClassifier I've ended using ITextBuffer.Properties to store my classifier instance, and if it already exists I just return a null classifier to stop the loop. It works in my limited tests, but I have no idea whether this is a valid and safe approach:
public IClassifier GetClassifier(ITextBuffer buffer)
{
if (buffer.Properties.TryGetProperty<EditorClassifier1>(typeof(EditorClassifier1), out var _))
{
return null;
}
else
{
EditorClassifier1 editorClassifier1 = new EditorClassifier1(classificationRegistry);
buffer.Properties.AddProperty(typeof(EditorClassifier1), editorClassifier1);
// Now I can call "aggregatorService.GetClassifier", since "editorClassifier1" is already added to "buffer.Properties",
// and this method will return null when called again.
editorClassifier1.Classifier = aggregatorService.GetClassifier(buffer);
return editorClassifier1;
}
}
What would be the best approach to retrieve the current classifications from my custom classifier?
Related
I'm using Laravel 8 and i want to get all the classes that implements an Interface X.
I did it with symfony4 few month ago with DI :
services.yml
_instanceof:
App\Calculator\Budget\BudgetCalculatorInterface:
tags: ['app.budget_calculator']
App\Handler\CalculatorBudgetHandler:
arguments: [!tagged app.budget_calculator]
and then in my class CalculatorBudgetHandler.php
private $calculatorList = [];
public function __construct(iterable $calculatorList)
{
$this->calculatorList = $calculatorList;
}
public function __construct(iterable $calculatorList)
{
$this->calculatorList = $calculatorList;
}
public function calculate(array $data): float
{
foreach ($this->calculatorList as $calculator) {
if ($calculator->supports($data)) {
return $calculator->calculate($data);
}
}
}
but i dot not understand how to do it with Laravel. I think i have to pass all my classes in a bind or tag :
$this->app->tag([CpuReport::class, MemoryReport::class], 'reports');
thats mean if i got a new class implementing X, i have to add it in the bind/tag ?
I want to do it automatically .
thx !
I needed this too. Looked for a longer time and I basically found a solution. The bad thing about this is that in PHP classes aren't actually declared when you did not use them. So you'll have to either scan the entire project for classes and test each class to find classes implementing your interface or (better) you use the composer autoload class maps. There you could probably limit the searching scope for classes to a sub namespace.
A small but cool package working this way is this one: https://gitlab.com/hpierce1102/ClassFinder - basically it uses composer PSR4 classmaps and is in general fine performance wise.
Here is the solution to which I came:
// Add to service provider
private function tagByInterface(string $interfaceName, string $tagName, string $rootNamespace)
{
foreach (ClassFinder::getClassesInNamespace($rootNamespace, ClassFinder::RECURSIVE_MODE) as $className) {
$class = new \ReflectionClass($className);
if ($class->isAbstract() || $class->isInterface()) {
continue;
}
if ($class->implementsInterface($interfaceName)) {
$this->app->tag($className, $tagName);
}
}
}
Which can then be used like this in the register():
$this->tagByInterface(SomeInterface::class, 'some-tag', 'App\Domain\Something');
$this->app->when(SomeClass::class)->needs('$myServices')->giveTagged('some-tag');
As the classes are loaded using reflection, this operation still might take time if your root namespace is not properly set or too wide. Reflection is quick (as far as I know quicker than loading the information from cache), but you should still think of using a deferred provider for the task so that the search for implementing classes only triggers when it's actually needed.
Update some months later
This solution works, but might be a huge drain on performance if the project gets big. I'm now caching the tagged classes. Something like this:
use HaydenPierce\ClassFinder\ClassFinder as HPClassFinder;
use Illuminate\Contracts\Cache\Repository;
class InheritanceClassFinder
{
public function __construct(private ?Repository $cache = null)
{
}
public function findClassesImplementingOrExtending(string $interfaceOrClass, string $rootNamespace): array
{
if ($this->cache) {
return $this->cache->rememberForever(
'inheriting-classes-'.$interfaceOrClass,
fn () => $this->findClassesInheriting($interfaceOrClass, $rootNamespace));
}
return $this->findClassesInheriting($interfaceOrClass, $rootNamespace);
}
private function findClassesInheriting(string $interfaceOrClass, string $rootNamespace): array
{
$classes = [];
foreach (HPClassFinder::getClassesInNamespace($rootNamespace, HPClassFinder::RECURSIVE_MODE) as $className) {
if (!is_subclass_of($className, $interfaceOrClass)
|| ($class = new \ReflectionClass($className))->isAbstract() || $class->isInterface()) {
continue;
}
$classes[] = $className;
}
return $classes;
}
}
This means as long as the cache is injected, stuff will be loaded once and then taken from cache. I inject the cache only in production, so locally its a bit slower but always up to date. In production I throw away the cache with every deployment, so I get a fresh load once after every deployment.
Is there a way to validate a property value when the property is evaluated? I can't do it in the getter because that returns the Property object - I want the validation to run only when the actual value is calculated (i.e. I want to be lazy evaluation friendly).
They show extensions using the Property object here:
https://docs.gradle.org/current/userguide/lazy_configuration.html#connecting_properties_together
However, they don't explain how to do property validation when the value is calculated. Here is the snipet of code from the Gradle documentation provided example:
// A project extension
class MessageExtension {
// A configurable greeting
final Property<String> greeting
#javax.inject.Inject
MessageExtension(ObjectFactory objects) {
greeting = objects.property(String)
}
}
If I wanted to make sure the value of greeting was not equal to test, then how would I do that when it is evaluated?
For most use cases, it should be sufficient to just validate the property value once you resolve it in your task or in other internal parts of your plugin. Only a few extensions are actually designed to be consumed by other plugins or the build script.
Gradle does not provide some validation that can be attached to a property, however you can build this functionality on your own like in the example below:
class MessageExtension {
private final Property<String> _greeting
final Provider<String> greeting
#javax.inject.Inject
MessageExtension(ObjectFactory objects) {
_greeting = objects.property(String)
greeting = _greeting.map { value ->
if (value.equals('test'))
throw new RuntimeException('Invalid greeting')
return value
}
}
def setGreeting(String value) {
_greeting.set(value)
}
def setGreeting(Provider<String> value) {
_greeting.set(value)
}
}
project.extensions.create('message', MessageExtension)
message {
greeting = 'test'
}
println message.greeting.get()
I turned the Property into a backing field for a Provider that runs the validation when resolved. If you do not want to throw an exception, but just return an empty Provider, you may replace the map with a flatMap.
I need to write a simple method that receives a parameter (e.g. a string) and does smth. Usually I'd end up with two tests. The first one would be a guard clause. The second would validate the expected behavior (for simplicity, the method shouldn't fail):
[Fact]
public void DoSmth_WithNull_Throws()
{
var sut = new Sut();
Assert.Throws<ArgumentNullException>(() =>
sut.DoSmth(null));
}
[Fact]
public void DoSmth_WithValidString_DoesNotThrow()
{
var s = "123";
var sut = new Sut();
sut.DoSmth(s); // does not throw
}
public class Sut
{
public void DoSmth(string s)
{
if (s == null)
throw new ArgumentNullException();
// do smth important here
}
}
When I try to utilize the FsCheck [Property] attribute to generate random data, null and numerous other random values are passed to the test which at some point causes NRE:
[Property]
public void DoSmth_WithValidString_DoesNotThrow(string s)
{
var sut = new Sut();
sut.DoSmth(s); // throws ArgumentNullException after 'x' tests
}
I realize that this is the entire idea of FsCheck to generate numerous random data to cover different cases which is definitely great.
Is there any elegant way to configure the [Property] attribute to exclude undesired values? (In this particular test that's null).
FsCheck has some built-in types that can be used to signal specific behaviour, like, for example, that reference type values shouldn't be null. One of these is NonNull<'a>. If you ask for one of these, instead of asking for a raw string, you'll get no nulls.
In F#, you'd be able to destructure it as a function argument:
[<Property>]
let DoSmth_WithValidString_DoesNotThrow (NonNull s) = // s is already a string here...
let sut = Sut ()
sut.DoSmth s // Use your favourite assertion library here...
}
I think that in C#, it ought to look something like this, but I haven't tried:
[Property]
public void DoSmth_WithValidString_DoesNotThrow(NonNull<string> s)
{
var sut = new Sut();
sut.DoSmth(s.Get); // throws ArgumentNullException after 'x' tests
}
I am using the XMLUnit in JUnit to compare the results of tests. I have a problem wherein there is an Element in my XML which gets the CURRENT TIMESTAMP as the tests run and when compared with the expected output, the results will never match.
To overcome this, I read about using org.xmlunit.diff.NodeFilters, but do not have any examples on how to implement this. The code snippet I have is as below,
final org.xmlunit.diff.Diff documentDiff = DiffBuilder
.compare(sourcExp)
.withTest(sourceActual)
.ignoreComments()
.ignoreWhitespace()
//.withNodeFilter(Node.ELEMENT_NODE)
.build();
return documentDiff.hasDifferences();
My problem is, how do I implement the NodeFilter? What parameter should be passed and should that be passed? There are no samples on this. The NodeFilter method gets Predicate<Node> as the IN parameter. What does Predicate<Node> mean?
Predicate is a functional interface with a single test method that - in the case of NodeFilter receives a DOM Node as argument and returns a boolean. javadoc of Predicate
An implementation of Predicate<Node> can be used to filter nodes for the difference engine and only those Nodes for which the Predicate returns true will be compared. javadoc of setNodeFilter, User-Guide
Assuming your element containing the timestamp was called timestamp you'd use something like
.withNodeFilter(new Predicate<Node>() {
#Override
public boolean test(Node n) {
return !(n instanceof Element &&
"timestamp".equals(Nodes.getQName(n).getLocalPart()));
}
})
or using lambdas
.withNodeFilter(n -> !(n instanceof Element &&
"timestamp".equals(Nodes.getQName(n).getLocalPart())))
This uses XMLUnit's org.xmlunit.util.Nodes to get the element name more easily.
The below code worked for me,
public final class IgnoreNamedElementsDifferenceListener implements
DifferenceListener {
private Set<String> blackList = new HashSet<String>();
public IgnoreNamedElementsDifferenceListener(String... elementNames) {
for (String name : elementNames) {
blackList.add(name);
}
}
public int differenceFound(Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
if (blackList.contains(difference.getControlNodeDetail().getNode()
.getParentNode().getNodeName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
public void skippedComparison(Node node, Node node1) {
}
I've implemented the specification pattern with Linq as outlined here https://www.packtpub.com/article/nhibernate-3-using-linq-specifications-data-access-layer
I now want to add the ability to eager load and am unsure about the best way to go about it.
The generic repository class in the linked example:
public IEnumerable<T> FindAll(Specification<T> specification)
{
var query = GetQuery(specification);
return Transact(() => query.ToList());
}
public T FindOne(Specification<T> specification)
{
var query = GetQuery(specification);
return Transact(() => query.SingleOrDefault());
}
private IQueryable<T> GetQuery(
Specification<T> specification)
{
return session.Query<T>()
.Where(specification.IsSatisfiedBy());
}
And the specification implementation:
public class MoviesDirectedBy : Specification<Movie>
{
private readonly string _director;
public MoviesDirectedBy(string director)
{
_director = director;
}
public override
Expression<Func<Movie, bool>> IsSatisfiedBy()
{
return m => m.Director == _director;
}
}
This is working well, I now want to add the ability to be able to eager load. I understand NHibernate eager loading can be done by using Fetch on the query.
What I am looking for is whether to encapsulate the eager loading logic within the specification or to pass it into the repository, and also the Linq/expression tree syntax required to achieve this (i.e. an example of how it would be done).
A possible solution would be to extend the Specification class to add:
public virtual IEnumerable<Expression<Func<T, object>>> FetchRelated
{
get
{
return Enumerable.Empty<Expression<Func<T, object>>>();
}
}
And change GetQuery to something like:
return specification.FetchRelated.Aggregate(
session.Query<T>().Where(specification.IsSatisfiedBy()),
(current, related) => current.Fetch(related));
Now all you have to do is override FetchRelated when needed
public override IEnumerable<Expression<Func<Movie, object>>> FetchRelated
{
get
{
return new Expression<Func<Movie, object>>[]
{
m => m.RelatedEntity1,
m => m.RelatedEntity2
};
}
}
An important limitation of this implementation I just wrote is that you can only fetch entities that are directly related to the root entity.
An improvement would be to support arbitrary levels (using ThenFetch), which would require some changes in the way we work with generics (I used object to allow combining different entity types easily)
You wouldn't want to put the Fetch() call into the specification, because it's not needed. Specification is just for limiting the data that can then be shared across many different parts of your code, but those other parts could have drastically different needs in what data they want to present to the user, which is why at those points you would add your Fetch statements.