Wait while the console still has information to print - eclipse

While developing an Eclipse plug-in, I want to output some paths in the console and then add some hyperlinks to those paths.
Instead of parsing the console, I thought about calculating the hyperlinks locations by the string which holds the path length which I print in console.
The problem which I have is that I try to create the hyperlink, but the information isn't printed yet in the console, therefore I get random bad location exceptions. It works if I run it in debug mode and I have a breakpoint on the hyperlink creation loop.
I tried to separate the creation of hyperlinks and wait until the messageQueue is empty, but that didn't work out.
private BlockingQueue<String> messageQueue = Queues.newLinkedBlockingQueue()
for ( String message : messages) {
messageQueue.offer(message);
// here I create a new HyperLinkInformation object and put it in a list
}
// wait until the queue is empty
while(!messageQueue.isEmpty()) {}
for (HyperLink hyperLinkObj : hyperlinkInformations) {
// try to create the hyperlink
}
Any ideas on how I could check if the console still has something to print?

Related

How to properly close Word documents after Documents.Open

I have the following code for a C# console app. It parses a Word document for textboxes and inserts the same text into the document at the textbox anchor point with markup. This is so I can convert to Markdown using pandoc, including textbox content which is not available due to https://github.com/jgm/pandoc/issues/3086. I can then replace my custom markup with markdown after conversion.
The console app is called in a PowerShell loop for all documents in a target list.
When I first run the Powershell script, all documents are opened and saved (with a new name) without error. But the next time I run it, I get an occasional popup error:
The last time you opened '' it caused a serious error. Do you still want to open it?
I can get through this by selecting yes on every popup, but this requires intervention and is tedious and slow. I want to know why this code results in this problem?
string path = args[0];
Console.WriteLine($"Parsing {path}");
Application word = new Application();
Document doc = word.Documents.Open(path);
try
{
foreach (Shape shp in doc.Shapes)
{
if (shp.TextFrame.HasText != 0)
{
string text = shp.TextFrame.TextRange.Text;
int page = shp.Anchor.Information[WdInformation.wdActiveEndPageNumber];
string summary = Regex.Replace(text, #"\r\n?|\n", " ");
Console.WriteLine($"++++textbox++++ Page {page}: {summary.Substring(0, Math.Min(summary.Length, 40))}");
string newtext = #$"{Environment.NewLine}TEXTBOX START%%%{text}%%%TEXTBOX END{Environment.NewLine}";
var range = shp.Anchor;
range.InsertBefore(Environment.NewLine);
range.Collapse();
range.Text = newtext;
range.set_Style(WdBuiltinStyle.wdStyleNormal);
}
}
string newFile = Path.GetFullPath(path) + ".notb.docx";
doc.SaveAs2(newFile);
}
finally
{
doc.Close();
word.Quit();
}
The console app is called in a PowerShell loop for all documents in a target list.
You can automate Word from your PowerShell script directly without involving any other dependencies. At least that will allow you to keep a single Word instance without creating each time a new Word Application instance for each document:
Application word = new Application();
Document doc = word.Documents.Open(path);
In the loop you could just open documents for processing and then closing them. It should improve the overall performance of your solution.
When you are done processing a document you need to close it by using the Close method which closes the specified document.
Also when a new Word Application instance is created, don't forget to close it as well by calling the Quit method which quits Microsoft Word and optionally saves or routes the open documents.
Application.Quit SaveChanges:=wdSaveChanges, OriginalFormat:=wdWordDocument

Stop huge error output from testing-library

I love testing-library, have used it a lot in a React project, and I'm trying to use it in an Angular project now - but I've always struggled with the enormous error output, including the HTML text of the render. Not only is this not usually helpful (I couldn't find an element, here's the HTML where it isn't); but it gets truncated, often before the interesting line if you're running in debug mode.
I simply added it as a library alongside the standard Angular Karma+Jasmine setup.
I'm sure you could say the components I'm testing are too large if the HTML output causes my console window to spool for ages, but I have a lot of integration tests in Protractor, and they are SO SLOW :(.
I would say the best solution would be to use the configure method and pass a custom function for getElementError which does what you want.
You can read about configuration here: https://testing-library.com/docs/dom-testing-library/api-configuration
An example of this might look like:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
You can then put this in any single test file or use Jest's setupFiles or setupFilesAfterEnv config options to have it run globally.
I am assuming you running jest with rtl in your project.
I personally wouldn't turn it off as it's there to help us, but everyone has a way so if you have your reasons, then fair enough.
1. If you want to disable errors for a specific test, you can mock the console.error.
it('disable error example', () => {
const errorObject = console.error; //store the state of the object
console.error = jest.fn(); // mock the object
// code
//assertion (expect)
console.error = errorObject; // assign it back so you can use it in the next test
});
2. If you want to silence it for all the test, you could use the jest --silent CLI option. Check the docs
The above might even disable the DOM printing that is done by rtl, I am not sure as I haven't tried this, but if you look at the docs I linked, it says
"Prevent tests from printing messages through the console."
Now you almost certainly have everything disabled except the DOM recommendations if the above doesn't work. On that case you might look into react-testing-library's source code and find out what is used for those print statements. Is it a console.log? is it a console.warn? When you got that, just mock it out like option 1 above.
UPDATE
After some digging, I found out that all testing-library DOM printing is built on prettyDOM();
While prettyDOM() can't be disabled you can limit the number of lines to 0, and that would just give you the error message and three dots ... below the message.
Here is an example printout, I messed around with:
TestingLibraryElementError: Unable to find an element with the text: Hello ther. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
...
All you need to do is to pass in an environment variable before executing your test suite, so for example with an npm script it would look like:
DEBUG_PRINT_LIMIT=0 npm run test
Here is the doc
UPDATE 2:
As per the OP's FR on github this can also be achieved without injecting in a global variable to limit the PrettyDOM line output (in case if it's used elsewhere). The getElementError config option need to be changed:
dom-testing-library/src/config.js
// called when getBy* queries fail. (message, container) => Error
getElementError(message, container) {
const error = new Error(
[message, prettyDOM(container)].filter(Boolean).join('\n\n'),
)
error.name = 'TestingLibraryElementError'
return error
},
The callstack can also be removed
You can change how the message is built by setting the DOM testing library message building function with config. In my Angular project I added this to test.js:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
This was answered here: https://github.com/testing-library/dom-testing-library/issues/773 by https://github.com/wyze.

Visual Studio Extension: Project context is applied to every opened file except the first one

I have a Visual Studio extension package where I am applying C++ syntax settings to custom file extensions. This is done in the Visual Studio's Text Editor options. Those files are plain text and I mean to have them behave as code files in the IDE (IntelliSense, find matching braces, etc...)
It's mostly working fine, but there is one problem. The C++ syntax context is not applied to whichever is the first file I open in a given Visual Studio session. I will launch Visual Studio, open one of our custom projects, and open one file. The IDE opens a document window and the file is opened, can be edited and saved, no problem in appearance. But the file behaves as a plain text and not a C++ source. Now, whenever I open a second file in the IDE, or any further file, the C++ settings do get applied successfully. I can close all document tabs, and open new ones, and all those tabs are fine. Even re-opening the first file in a new tab, or after re-loading the project or the solution, is fine. Only the first document opened in a Visual Studio session has the issue.
For the following segment, I will refer to the Microsoft documentation on using their standard editor: https ://msdn.microsoft.com/en-us/library/bb166504.aspx
To implement the OpenItem method with a standard editor
1.Call IVsRunningDocumentTable (RDT_EditLock) to determine whether the document data object file is already open.
2.If the file is already open, resurface the file by calling the IsDocumentOpen method, specifying a value of IDO_ActivateIfOpen for the grfIDO parameter.
If the file is open and the document is owned by a different project than the calling project, your project receives a warning that the editor being opened is from another project. The file window is then surfaced.
3.If the document is not open or not in the running document table, call the OpenStandardEditor method (OSE_ChooseBestStdEditor) to open a standard editor for the file.
When you call the method, the IDE performs the following tasks:
a.The IDE scans the Editors/{guidEditorType}/Extensions subkey in the registry to determine which editor can open the file and has the highest priority for doing this.
b.After the IDE has determined which editor can open the file, the IDE calls CreateEditorInstance. The editor's implementation of this method returns information that is required for the IDE to call CreateDocumentWindow and site the newly opened document.
c.Finally, the IDE loads the document by using the usual persistence interface, such as IVsPersistDocData2.
d.If the IDE has previously determined that the hierarchy or hierarchy item is available, the IDE calls GetItemContext method on the project to get a project-level context IServiceProvider pointer to pass back in with the CreateDocumentWindow method call.
4.Return an IServiceProvider pointer to the IDE when the IDE calls GetItemContext on your project if you want to let the editor get context from your project.
Performing this step lets the project offer additional services to the editor.
If the document view or document view object was successfully sited in a window frame, the object is initialized with its data by calling LoadDocData.
It definitely seems to me that I need to hit element (D) from the above instructions. I have debuged through my extension code, and I do see where my implementation of GetItemContext() comes into play. When I open most files, the code path does effectively go through this method, however it does not when I open the first file of a Visual Studio session.
Call stack from OpenStandardEditor
GetItemContext is invoked by the Microsoft assemblies and I do not know what is the condition that triggers whether it is called or not. I can only trace up to my call to the method OpenStandardEditor(), in FileDocumentManager.cs, then I don't know what happens beyond that. The above screenshot is the call stack when GetItemContext is successfully invoked, but when I'm opening the first file I'm totally in the dark as to what OpenStandardEditor is doing. I do know that in both cases, when the context is loaded and when it is not, the exact same parameter values are passed to OpenStandardEditor. So here's my code where this method is invoked, if that can be of some help:
My override of class DocumentManager:
private int Open(bool newFile, bool openWith, uint editorFlags, ref Guid editorType, string physicalView, ref Guid logicalView, IntPtr docDataExisting, out IVsWindowFrame windowFrame, WindowFrameShowAction windowFrameAction)
{
windowFrame = null;
if (this.Node == null || this.Node.ProjectMgr == null || this.Node.ProjectMgr.IsClosed)
{
return VSConstants.E_FAIL;
}
int returnValue = VSConstants.S_OK;
string caption = this.GetOwnerCaption();
string fullPath = this.GetFullPathForDocument();
// Make sure that the file is on disk before we open the editor and display message if not found
if (!((FileNode)this.Node).IsFileOnDisk(true))
{
// Inform clients that we have an invalid item (wrong icon)
this.Node.OnInvalidateItems(this.Node.Parent);
// Bail since we are not able to open the item
return VSConstants.E_FAIL;
}
IVsUIShellOpenDocument uiShellOpenDocument = this.Node.ProjectMgr.Site.GetService(typeof(SVsUIShellOpenDocument)) as IVsUIShellOpenDocument;
IOleServiceProvider serviceProvider = this.Node.ProjectMgr.Site.GetService(typeof(IOleServiceProvider)) as IOleServiceProvider;
try
{
int result = VSConstants.E_FAIL;
if (openWith)
{
result = uiShellOpenDocument.OpenStandardEditor((uint)__VSOSEFLAGS.OSE_UseOpenWithDialog, fullPath, ref logicalView, caption, this.Node.ProjectMgr, this.Node.ID, docDataExisting, serviceProvider, out windowFrame);
}
else
{
__VSOSEFLAGS openFlags = 0;
if (newFile)
{
openFlags |= __VSOSEFLAGS.OSE_OpenAsNewFile;
}
//NOTE: we MUST pass the IVsProject in pVsUIHierarchy and the itemid
// of the node being opened, otherwise the debugger doesn't work.
if (editorType != Guid.Empty)
{
result = uiShellOpenDocument.OpenSpecificEditor(editorFlags, fullPath, ref editorType, physicalView, ref logicalView, caption, this.Node.ProjectMgr, this.Node.ID, docDataExisting, serviceProvider, out windowFrame);
}
else
{
openFlags |= __VSOSEFLAGS.OSE_ChooseBestStdEditor;
// THIS IS THE CALL THAT I'M ALWAYS INVOKING. PARAMS ARE ALWAYS THE SAME, BUT ITEM CONTEXT IS NOT ACTIVATED FOR FIRST FILE OF A SESSION.
result = uiShellOpenDocument.OpenStandardEditor((uint)openFlags, fullPath, ref logicalView, caption, this.Node.ProjectMgr, this.Node.ID, docDataExisting, serviceProvider, out windowFrame);
}
}
if (result != VSConstants.S_OK && result != VSConstants.S_FALSE && result != VSConstants.OLE_E_PROMPTSAVECANCELLED)
{
ErrorHandler.ThrowOnFailure(result);
}
if (windowFrame != null)
{
object var;
if (newFile)
{
ErrorHandler.ThrowOnFailure(windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out var));
IVsPersistDocData persistDocData = (IVsPersistDocData)var;
ErrorHandler.ThrowOnFailure(persistDocData.SetUntitledDocPath(fullPath));
}
var = null;
ErrorHandler.ThrowOnFailure(windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_DocCookie, out var));
this.Node.DocCookie = (uint)(int)var;
if (windowFrameAction == WindowFrameShowAction.Show)
{
ErrorHandler.ThrowOnFailure(windowFrame.Show());
}
else if (windowFrameAction == WindowFrameShowAction.ShowNoActivate)
{
ErrorHandler.ThrowOnFailure(windowFrame.ShowNoActivate());
}
else if (windowFrameAction == WindowFrameShowAction.Hide)
{
ErrorHandler.ThrowOnFailure(windowFrame.Hide());
}
}
}
catch (COMException e)
{
Trace.WriteLine("Exception e:" + e.Message);
returnValue = e.ErrorCode;
this.CloseWindowFrame(ref windowFrame);
}
return returnValue;
}
I have also tried an alternative. In the call stack where I perform DoDefaultAction on my FileNode (extends HierarchyNode), I normally call an instance of my DocumentManager.Open() directly. I have changed that to try OpenDocumentViaProject() instead. Now, the MSENV assembly turns out to call my GetItemContext, then goes out to my implementation of DocumentManager.Open I quoted above.
Call stack from OpenDocumentViaProject
Sounds promising... but no. Beyond the screenshot above, once I call OpenStandardEditor the exact same behavior happens. No project context is applied to the first document opened in a session, and the context is applied to every further file. The call to GetItemContext() that is done by OpenDocumentViaProject() does not seem to matter in the slightest. Only when OpenStandardEditor() also ends up calling GetItemContext() somewhere downstream does the project settings I want get applied.
I don't see where I would be doing something fundamentally wrong. It seems to me that I am following the Mimcrosoft instructions on opening standard editors. Would you have a clue as to how my GetItemContext implementation is not invoked when I'm opening the first file of a VS session? Thanks

Bulk logging using Enterprise library

Hi i am using Enterprise library 5.0 to log messages in text file, as a part of that i need to log collection of messages to the text file .
Below is the part of code which logs to text file using flatfilelistener
public void LogToFile(string message, string category, IDictionary<string, object> additionalDetail)
{
var logger = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
logger.Write(message, category, 0, 0, TraceEventType.Error, string.Empty, additionalDetail);
}
The above will log single message in text file, like that i will call for each item in collection which i need to log.
So , how to log everything in single stretch? like placing in buffer and updating logfile on single stretch.
I guess there is one property named "AutoFlush" but i don't know how to use that.
using auto flush
That is likely your best bet. Just let the buffer handle it or create a custom flush mechanism that you can call at a specified duration such as the end of a http request or if you are paranoid perhaps when an application crashes and you can't trust autoflush to work.

Intrincate sites using htmlunit

I'm trying to dump the whole contents of a certain site using HTMLUnit, but when I try to do this in a certain (rather intrincate) site, I get an empty file (not an empty file per se, but it has an empty head tag, an empty body tag and that's it).
The site is https://www.abcdin.cl/abcdin/abcdin.nsf#https://www.abcdin.cl/abcdin/abcdin.nsf/linea?openpage&cat=Audio&cattxt=TV%20y%20Audio&catpos=03&linea=LCD&lineatxt=LCD%20&
And here's my code:
BufferedWriter writer = new BufferedWriter(new FileWriter(fullOutputPath));
HtmlPage page;
final WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
webClient.setCssEnabled(false);
webClient.setPopupBlockerEnabled(true);
webClient.setRedirectEnabled(true);
webClient.setThrowExceptionOnScriptError(false);
webClient.setThrowExceptionOnFailingStatusCode(false);
webClient.setUseInsecureSSL(true);
webClient.setJavaScriptEnabled(true);
page = webClient.getPage(url);
dumpString += page.asXml();
writer.write(dumpString);
writer.close();
webClient.closeAllWindows();
Some people say that I need to introduce a pause in my code, since the page takes a while to load in Google Chrome, but I set long pauses and it doesn't work.
Thanks in advanced.
Just some ideas...
Retrieving that URL with wget returns a non-trivial HTML file. Likewise running your code with webClient.setJavaScriptEnabled(false). So it's definitely something to do with the Javascript in the page.
With Javascript enabled, I see from the logs that a bunch of Javascript jobs are being queued up, and I get see corresponding errors like this:
EcmaError: lineNumber=[49] column=[0] lineSource=[<no source>] name=[TypeError] sourceName=[https://www.abcdin.cl/js/jquery/jquery-1.4.2.min.js] message=[TypeError: Cannot read property "nodeType" from undefined (https://www.abcdin.cl/js/jquery/jquery-1.4.2.min.js#49)]
com.gargoylesoftware.htmlunit.ScriptException: TypeError: Cannot read property "nodeType" from undefined (https://www.abcdin.cl/js/jquery/jquery-1.4.2.min.js#49)
at
com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:601)
Maybe those jobs are meant to populate your HTML? So when they fail, the resulting HTML is empty?
The error looks strange, as HtmlUnit usually has no issues with JQuery. I suspect the issue is with the code calling that particular line of the JQuery library.