Is there any way to remove attribute after the attribute was added by AddAttribute (msdn)?
Example:
public static void GenerateFieldInput(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.AddAttribute("placeholder", "some value");
// some code logic
writer.RemoveAttribute("placeholder"); // there isn't such method in HtmlTextWriter
}
HtmlTextWriter, like many other TextWriters, only writes stuff into a stream. There isn't an official way to delete stuff from it.
And why do you want to remove the attribute in the first place? Did you find that later on in the code, that the attribute is not needed anymore? If that's the case, try determining whether the tag is actually needed before you write it.
If you can't do that, you can put all the attributes you want to add in a List<T>, which allows you to add and delete elements. After you are absolutely sure that that is what you are going to write, do a foreach loop and write each attribute.
Related
I am following this tutorial, https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix
What I really want is to detect if a method in a ASP.Net Web API controller is missing my Custom attribute and give hints to the developer to add it.
In my Analyzer's Initilize method, I have chosen MethodDeclaration as the SyntaxKind like this
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.MethodDeclaration);
In the AnalyzeNode method, I want to detect if the method in question already has the Custom attribute added to it.
private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var methodDeclaration = (MethodDeclarationSyntax)context.Node;
// make sure the declaration isn't already const:
if (methodDeclaration.AttributeLists.Any(x=> x. ))
{
return;
}
Not sure what needs to be done in this piece of code to find if Custom attribute is already applied.
Eventually I want my code analyzer to let the user add the missing attribute
[Route("/routex")]
[Custom()]
public async Task<IHttpActionResult> AlreadyHasCustomAttribute()
{
//everything is good, no hint shown to the user
}
[Route("/routey")]
public async Task<IHttpActionResult> DoesNotHaveCustomAttribute()
{
//missing Custom attribute, show hint to the user and add the attribute as a code fix
}
Please suggest a solution. Thanks.
The easiest thing might be to simply call methodDeclaration.AttributeLists.Any()) just to verify it has attributes at all before proceeding for performance reasons. Once it does, you can call context.SemanticModel.GetDeclaredSymbol(methodDeclaration) and that'll give you an IMethodSymbol which you can call GetAttributes() on. From there, you can walk the list of attributes and find the one you're looking for (or in this casel, find the lack of it.)
There isn't one way to do it. The way I'd personally do this is to first register a compilation start action and get the attribute symbol. Then register a symbol action, and for each method check if any of the attributes match the attribute obtained in compilation start.
This would look similar to the following
context.RegisterCompilationStartAction(context =>
{
var targetAttribute = context.Compilation.GetTypeByMetadataName("FullyQualifiedAttributeName");
if (targetAttribute is null)
{
// Do whatever you want if the attribute doesn't exist in the first place.
// Stopping the analysis is probably the best option?
return;
}
context.RegisterSymbolAction(context =>
{
var methodSymbol = (IMethodSymbol)context.Symbol;
if (!methodSymbol.GetAttributes().Any(attrData => targetAttribute.Equals(attrData.AttributeClass, SymbolEqualityComparer.Default))
{
// attribute is missing.
// though it doesn't make sense to report a missing attribute for all methods in a compilation, so you'll likely need extra checks based on the logic of your analyzer.
}
}, SymbolKind.Method);
});
I have a method below where I enter in a postcode, select the find address button and I expect some fields to be visible:
public void CompletePostcodeLookup()
{
_driver.FindElement(PaymentDetailsResponsiveElements.PostcodeLookupField).SendKeys("LS11 9AW");
_driver.FindElement(PaymentDetailsResponsiveElements.FindAddressBtn).Click();
_driver.WaitToBeInvisible(PaymentDetailsResponsiveElements.FindAddressBtn, 5);
_driver.WaitToBeVisible(PaymentDetailsResponsiveElements.AddressManualHouseNumberField, 5);
_driver.WaitToBeVisible(PaymentDetailsResponsiveElements.AddressLineOneField, 5);
_driver.WaitToBeVisible(PaymentDetailsResponsiveElements.AddressCityField, 5);
_driver.WaitToBeVisible(PaymentDetailsResponsiveElements.AddressManualPostcodeField, 5);
_driver.WaitToBeVisible(PaymentDetailsResponsiveElements.AddressCounty, 5);
}
Now not only am I expecting the fields to be visible, but these fields should be valld and in the HTML we can determine these fields are valid based on this...
<input... aria-invalid='false'>
So what i did in my PaymentDetailsResponsiveElements.cs page is included a method that finds any input that contains this:
public static By ValidFields => By.XPath("//input[#aria-invalid='false']");
Now this may be the icorrect way of doing things but I wanted to know that if I wanted to check that all of these visiable fields are valid, what is the correct way to code it? Should i even place them in an 'Assert'?
Edit:
I included all methods into one method, if I can do an assertion based on none of these methods have an invalid field then should be ok:
public void CompleteContactDetailsForm()
{
SelectBookingContact();
CompletePostcodeLookup();
CompletePhoneNumberFields();
CompleteEmailAddressFields();
}
Thanks
1st way:
You may consider writing a for loop to check that each webElement has value: invalid='false' (you may do this by writing simple parser)
2nd way:
You can do it by reading complete list of desired Web elements in an Array List and iterate through it using iterator like here
Regarding Assert, that should be placed on final step (.cs file where you are calling this case).
I have a question. I need to check when was a method last modified. I know how to check this for files but didn't find anything how can i check just a method. The assignment i have to do is the following:
Write a LastModifiedAttribute that can be applied to a method. The
attribute should specify the date and programmer who last touched the
method and possibly an enumerated value of why the method was changed
(new feature, defect correction, etc.). Write a program that loads an
assembly and lists the classes and methods, sorted by their
lastmodified date.
If somebody can help with the last part of the assigment too about the programmer and the enumerated value i would appricate that too, but i'm mainly interested in the method last modified date. Thx anticipated
It sounds like you need a custom attribute.
You can make it work on methods alone using
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
...
public MyAttribute(string name, DateTime lastChanged, CustomEnum reason)
{
...
This does not automatically find out when the method was last modified and why. That information is not present in the files, and your assignment doesn't say it is. You need a separate program to generate appropriate attribute tags from whatever version control system you use, or you can rely on the programmers to create appropriate tags.
In the Resharper API, JetBrains.Resharper.Psi.Csharp.Tree.AddAttributeBefore takes an IAttribute param, and an IAttribute anchor. How are these arguments different, and how can they be constructed?
Have a peek at the working with XML document inside it shows use of the AddAttributeBefore call the first is the attribute you wish to insert. The second one is a attribute that already exists that you wish to insert before. If the second attribute is NULL the new attribute is inserted after the last attribute.
basically, the param is what you want to add, and anchor is the element before which you want to add something. Keep in mind that you can, in most cases, have anchor == null, which would cause the element to be added last.
I'm implementing a custom XmlTextWriter and I'd like to omit any elements with a particular name that contain no attributes. I've gotten as far as being able to prevent the element from being written by overriding WriteStartElement and WriteEndElement, but is there a way to know at WriteStartElement or at any other useful point whether or not the element has any attributes?
No. However you can postpone writing of the element and attributes (put them in a field) until you get to the next element/comment/etc. Then decide whether you want to write them or not.