Visual Studio Custom Language Service - c#

I am attempting to implement a Language Service in a VSPackage using the MPF, and it's not working quite as I understand it should.
I have several implementations already, such as ParseSource parsing the input file with a ParseRequest. However, when it finds an error, it adds it with AuthoringSink.AddError. The documentation for this implies it adds it to the Error List for me; it doesn't.
I also have a simple MySource class, a subclass of Source. I return this new class with an overridden LanguageService.CreateSource method. The documentation for OnCommand says it's fired 'when a command is entered'. However, it's not.
There's obviously some intermediate step which I haven't done correctly. I've already rambled enough, so I'll be glad to give any additional details by request.
Any clarification is much appreciated.

For the AuthoringSink error list question, I use this behavior in my Language Service. In ParseSource, the ParseRequest class has an AuthoringSink. You can also create a new ErrorListProvider if you want to work outside of the parser's behavior. Here is some example code:
error_list = new ErrorListProvider(this.Site);
error_list.ProviderName = "MyLanguageService Errors";
error_list.ProviderGuid = new Guid(this.errorlistGUIDstring.);
}
ErrorTask task = new ErrorTask();
task.Document = filename;
task.CanDelete = true;
task.Category = TaskCategory.CodeSense;
task.Column = column;
task.Line = line;
task.Text = message;
task.ErrorCategory = TaskErrorCategory.Error;
task.Navigate += NavigateToParseError;
error_list.Tasks.Add(task);
I hope this was helpful.
OnCommand should be firing every time there is a command, in your MySource class you can do something like this (pulled from working code):
public override void OnCommand(IVsTextView textView, VsCommands2K command, char ch)
{
if (textView == null || this.LanguageService == null
|| !this.LanguageService.Preferences.EnableCodeSense)
return;
if (command == Microsoft.VisualStudio.VSConstants.VSStd2KCmdID.TYPECHAR)
{
if (char.IsLetterOrDigit(ch))
{
//do something cool
}
}
base.OnCommand(textView, command, ch);
}
If that doesn't work double check that CodeSense = true in your ProvideLanguageService attribute when you setup your LanguageService package. A whole lot of what is cool to do in the LanguageService requires these attributes to be correctly turned on. Some even give cool behaviors for free!
Another thing to be careful of is that some behaviors like colorizer don't function correctly in the hive in my experience. I don't think these were ones that gave me trouble, but I implemented these a couple of years ago so I'm mostly just looking back at old code.

AuthoringSink.AddError only adds errors to the error list if ParseRequest.Reason is ParseReason.Check. When your ParseSource function attempts to add errors while parsing for any other ParseReason, nothing will happen.
It's possible that your language service is never calling ParseSource with this ParseReason. As far as I know, the only way to get a ParseReason of Check (outside of manually calling BeginParse or ParseSource yourself) is to proffer your service with an idle timer.

Related

How to add attachments to Allure report in C#?

The Allure framework is a really beautiful framework for test reporting.
Yet it has rather bad documentation for C#.
I want to add some things to my allure report:
Debug log (like all things I write to debug)
Screenshot
A file
How to do it? I have no idea, please help me if you know how to do it. It seems like AllureLifecycle class can help me but I'm not sure how to use it.
In case it matters I use Allure together with SpecFlow and MS test.
I searched more and seems I found the Truth.
And the Truth is it's possible to add all attachments I wanted but they can be added only as a file:
byte[] log = Encoding.ASCII.GetBytes(Log.GetAllLog());
AllureLifecycle.Instance.AddAttachment("DebugLog", "application/json", log, "json");
If you want to add a file from actually a path (location) you can do it with the same method but a different overload.
So just place this code in a "teardown\afterscenario" method or at any other place (for example at "afterstep" method) where you want to make this attachment. I use SpecFlow so if I add this to "AfterStep" hook then Allure displays those files attached to a specific step! That's amazing!)
it seems that allure has some events that can be used.
See : https://github.com/allure-framework/allure-csharp-commons/blob/master/AllureCSharpCommons.Tests/IntegrationTests.cs for more information.
haven't tried it myself, but something like this should work according to the documentation.
_lifecycle = Allure.DefaultLifecycle;
_lifecycle.Fire(new
MakeAttachmentEvent(AllureResultsUtils.TakeScreenShot(),
"Screenshot",
"image/png"));
_lifecycle.Fire(new MakeAttachmentEvent(File.ReadAllBytes("TestData/attachment.json"),
"JsonAttachment",
"application/json"));
Hope this helps.
Using this kind of code in AfterScenario method:
if (_scenarioContext.TestError != null)
{
var path = WebElementsUtils.MakeScreenshot(_driver);
_allureLifecycle.AddAttachment(path);
}
First it verifies, if Scenario passed, if not then
WebElementsUtils.MakeScreenshot(_driver)
method makes screenshot and returns it's path. Then this path I giving to Allure. As a second parameter in the same method I can give a name of the screenshot. As a result I am getting a screenshot in AfterScenario block in Allure report.
P.S. This is only for screenshots, about logs can't tell nothing.
With this example you can add an attachment exactly to the failed step
[AfterStep(Order = 0)]
public void RecordScreenFailure(ScenarioContext scenarioContext)
{
if (scenarioContext.TestError != null)
{
Allure.Commons.AllureLifecycle allureInstance = Allure.Commons.AllureLifecycle.Instance;
string screenshotPath = MagicMethodMakingScreenshotAndReturningPathToIt();
allureInstance.UpdateTestCase(testResult => {
Allure.Commons.StepResult failedStepRsult =
testResult.steps.First(step => step.status == Allure.Commons.Status.failed);
failedStepRsult.attachments.Add(new Allure.Commons.Attachment() {
name = "failure screen",
source = screenshotPath,
type = "image/png"
});
});
}
}

Saving Modules correctly using Access-Interop

Even though my last questions weren't accepted well, I will give it another try.
I'm working on a program that is capable of controlling a lot of office-application behaviour by using the COM/Interop-Interface Microsoft provided for Word/Access/Excel. Still some functions differ from each other in the way that they are kept specific for the program that gets addressed.
My ambition is to Insert Macro-Code to an existing Access-Database and run the code while the Database is open and delete the code before the Database closes down. Partially this works as wished by using following C# code:
VBProject found = null;
Access.Application currApplication = this._currentInstance.Application;
if (target.Equals("") || scriptText.Equals(""))
return false;
foreach (VBProject vb in currApplication.VBE.VBProjects)
{
if (currApplication.CurrentDb().Name.Equals(vb.FileName))
{
found = vb;
break;
}
}
if (found != null)
{
foreach (VBComponent foundComponent in found.VBComponents)
{
if (foundComponent.Name.Equals(target))
{
return true;
}
}
VBComponent module = found.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
module.Name = target;
module.CodeModule.AddFromString(scriptText);
return true;
}
else
{
return false;
}
Now in particular, Access makes a diversion between VBA-Code-Modules which are visible in the Code-Editor and Modules which are loaded into the Database itself. For inserting the Module into the Database, it needs to be saved another time. When using the GUI, there's a window that popsup and asks for the Name to be used when saving it into the DB. It already takes the correct one etc. and it's fine after doing it by hand.
Besides the manual solution I found no way to do this step programatically.
Initial thoughts were:
currApplication.DoCmd.OpenModule(target, Type.Missing);
currApplication.DoCmd.Save(Access.AcObjectType.acMacro, target);
or
found.VBE.ActiveVBProject.SaveAs("");
The only two methods I could imagine would be doing the step I wanted. VBE in it's new .NET compatible form is documented very bad. Methods that would have applied to the native version are not guilty anymore. So I'm stuck with it now.
In case someone asks, why would you save the module at all, because once it's inserted in VBE it can be run like any other module listed in Access also, that's true, but for some unknown reasons this seems to be more fault-prone then to save it twice. Got runtime errors (like 2501) while launching the macro, which is not the case when it's saved properly.
Keeping it forever in the Access-Databases would be the last option but since those are many MDBs and thus they are changing frequently, I thought it would be nice to have it dynamic.
Hope somebody understands what I wrote here, (not so easy for me), and is enabled to help somehow :)
Thanks for all the reading. Looking forward for some good results, from the best community, hehe.

Application changes not taking effect

I have made a change to a method used in a Functiod in a mapping file but it seems the new code is not taking effect, ever.
I have deployed properly, started the application, restarted related host instance (actually all host instances I could find) and still, the old code seems to execute.
Here's the, simple, method:
public string RemoveNonNumericChars(string stIn, int maxLength)
{
string strOut;
try
{
strOut = Regex.Replace(stIn, "[^0-9]", "");
System.Diagnostics.EventLog.WriteEntry("BizTalk Server 2009", strOut);
return strOut.Substring(0, maxLength);
}
catch
{
return string.Empty;
}
}
I added the writing to EventLog line to see that this code is indeed being executed, but I don't get anything in "Application" event logs.
I do NOT get an empty string being returned, so it really does seem like the old code that's being executed prior to me fixing the method.
What am I missing exactly ?
Thank you.
For some reason, the script is not able to correctly retrieve the Build Config selected in Visual Studio, it's taken from Debug when I'm actually trying to build it for a Test environment. I should have known, thanks anyways.

How do you actually implement the Search Contract? (C#)

I'm having some trouble understanding and getting the search contract to work in my Store app. I have been unable to find any sort of documentation or guide that explains the structure of using the contract. (I've looked at the quickstarts on MSDN, the Search Contract sample and the build video, but that only really deals with javascript)
So far I've been able to run a query and get a list (of Custom Objects) into my search contract page, and from there I try to assign that to defaultviewmodel.results, but no matter what query I type nothing shows up I on the page. Is there something else I need to set?
What I have so far is as follows (excerpts):
App.xaml.cs
protected override void OnSearchActivated(Windows.ApplicationModel.Activation.SearchActivatedEventArgs args)
{
SearchCharmResultsPage.Activate(args.QueryText, args.PreviousExecutionState);
SearchCharmResultsPage.ProcessSearchQuery(args.QueryText);
}
public async static void ProcessSearchQuery(string queryString)
{
try
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("recipeCustomObject Debug.WriteLine("Database exists, connecting");
SQLiteAsyncConnection connection = new SQLiteAsyncConnection("CustomObject_db");
List<CustomObject> resultsList = new List<CustomObject>();
string query = "SELECT * FROM CustomObjectDB";
resultsList = await connection.QueryAsync<RecipeRecord>(query);
}
catch (FileNotFoundException fnfExc)
{
Debug.WriteLine("FNFEXC: " + fnfExc.ToString());
}
}
I think it is possible that here lies the problem, though I'm not sure if it is, or how to change it.
the resultsList list is created here, but because the method it asynchronous, I can't return from the method. Because of this I'm guess that when I try to assign this.DefaultViewModel[Results] = resultsList; in the LoadStateMethod, the object doesn't exist (thought the program throws no error). When I try to add the same line in the ProcessSearchQuery method, i'm told that this is not valid in a static method, but I think I need the method to be static? My problem might just be a fundamental logic error?
Finally got it! found the solution here: http://jeffblankenburg.com/2012/11/06/31-days-of-windows-8-day-6-search-contract
For those looking for an answer in the future, the key is to make sure you have your search logic within the Filter_SelectionChanged method, which was something I wasn't doing. Look at the guide within the above link to get an idea of the structure.
Have you looked at the Search contract sample on the developer center? There's a C#/XAML version there as well.
My open source Win8 RSS Reader framework implements Search (and Share) have a look at the source and if you still got questions, I'll be happy to help http://win8rssreader.codeplex.com/

Question about Microsoft robotics developer studio sample code

If anyone has come across the the Arcos sample code in the MRDS can you please let me know what the following code fragment does in the ArcosDrive.cs file. I am more interested in the lines "arcos.Update update = new arcos.Update(raw);" and "_arcosPort.Post(update);".
Thanks.
void VelocityHandler(Velocity velocity)
{
arcos.RawType raw = new arcos.RawType();
raw.Command = "Vel";
raw.Integer = (short)velocity.Body.Velocity;
raw.Flags = arcos.RawFlags.Integer;
arcos.Update update = new arcos.Update(raw);
_arcosPort.Post(update);
Activate(Arbiter.Choice(update.ResponsePort,
delegate(DefaultUpdateResponseType response)
{
velocity.ResponsePort.Post(DefaultSubmitResponseType.Instance);
},
delegate(Fault fault)
{
velocity.ResponsePort.Post(fault);
})
);
}
After taking a deep breath and careful thinking :P I managed to figure it out.
Seems that a PostUnknownType is like an automatic type casting whereby the type that is posted is recognized automatically without having to define multiple post types.
In the case of RawType, a RawType post eventually triggers a call to RawCommandHandler defined in the ArcosState class.
Hope someone finds this useful.

Categories

Resources