Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IDE: Fix YAML parsing issue affecting Document.selectedString_ #2849

Merged
merged 3 commits into from
May 7, 2017
Merged

IDE: Fix YAML parsing issue affecting Document.selectedString_ #2849

merged 3 commits into from
May 7, 2017

Conversation

mossheim
Copy link
Contributor

Issue

Document.current.selectedText_("abc");

Expected behavior: add abc to current document.
Actual behavior: nothing.

Diagnosis

In DocumentManager::handleSetDocTextScRequest, which is called to set document text in the IDE, the parameter funcID is Null in many instances, which would cause the function to bail out early while trying to parse a null node as a string:

std::string funcID = doc[1].as<std::string>(); // throws if doc[1].IsNull()

Solution

After this commit, funcID is only parsed if it is not null, and a function call to Document.executeAsyncResponse is, again, only made if the funcID is non-null.

Other notes

I added debugging code to the try-catch blocks in this file so this is easier to diagnose in the future. I don't have time to check if any other functions are similarly afflicted with early exits, but thought it would be helpful not to cover my tracks here. The macro to define is SC_DEBUG_DOC_MANAGER.

A less intrusive option would have been to add a fallback:

std::string funcID = doc[1].as<std::string>(""); // will return an empty string instead of throwing

However, this would cause a call to

Document.executeAsyncResponse('');

even if funcID were null, which is not expected behavior, since you actually could add the association '' -> { /* do something */ } to an IdentityDictionary.

funcID is nil in many instances, which would cause
handleSetDocTextScRequest to bail out early while trying to parse a
null node as a string.

After this commit, funcID is only parsed if it is not null, and
a function call to Document.executeAsyncResponse is, again, only
made if the funcID is non-null.
Adds some simple debugging code that posts errors in catch blocks
for YAML parsing. Enabled by defining SC_DEBUG_DOC_MANAGER.
@mossheim mossheim changed the title IDE: Fix set doc text yaml parsing IDE: Fix YAML parsing issue affecting Document.selectedString_ Apr 23, 2017
@mossheim
Copy link
Contributor Author

mossheim commented Apr 23, 2017

Aside: is this debug messaging convention OK? I know it isn't really seen elsewhere in the codebase. My thinking was that sending to cerr is probably more reliable because the IDE has its cout/stdout redirected. It's also easier to scan for relevant messages in the console or a redirected log file rather than the mix of debug/non-debug info in the IDE post window.

@mossheim mossheim requested review from muellmusik and removed request for muellmusik April 23, 2017 14:47
@nhthn
Copy link
Contributor

nhthn commented Apr 23, 2017

I can confirm that this fixes the issue.

@jamshark70
Copy link
Contributor

Likewise confirmed, selectedString_ is working with this fix.

I'm unclear on the right place to define SC_DEBUG_DOC_MANAGER (these magical things that C++ folks "just know" and the rest of us don't).

@mossheim
Copy link
Contributor Author

mossheim commented Apr 24, 2017

@jamshark70 you can just add a #define right before the #ifdef, that's what I was doing. :) I think there's a way to sneakily pass arbitrary preprocessor defines through Cmake, but I haven't got that down yet (it's not -D).

@bagong
Copy link
Contributor

bagong commented Apr 24, 2017

This is an example how a variable that is passed in via -D (fortify) is turned into a definition:

https://github.com/supercollider/supercollider/blob/master/CMakeLists.txt#L285

@mossheim
Copy link
Contributor Author

Right, but as far as arbitrary defines go, AFAICT you have to edit the makefiles to get it to work.

@bagong
Copy link
Contributor

bagong commented Apr 24, 2017

Is this arbitrary enough? :)

https://github.com/supercollider/supercollider/blob/master/CMakeLists.txt#L107

@mossheim
Copy link
Contributor Author

Ah okay, I figured it out. You can add flags to Cmake's compiler invocation flags. Adding the #define was a lot easier for me, haha.

cmake -DCMAKE_C_FLAGS="-D SC_DEBUG_DOC_MANAGER" -DCMAKE_CXX_FLAGS="-D SC_DEBUG_DOC_MANAGER" ..

@bagong I was looking for an arbitrarily named macro, not an arbitrary value for one already recognized by the Cmake project.

@bagong
Copy link
Contributor

bagong commented Apr 24, 2017

Well, I thought you create an option in the cmake script that creates the define with add_definitions if set. That's how its often done. Thereby it's implicitly documented. The line above looks scary to me, doesn't that override other compiler flags? (Hehe, but I'm not sure... just go ahead, I am sure you know what you're doing... Might take others as long as it took you, though, to find that possibility ;))

@mossheim
Copy link
Contributor Author

@bagong

The line above looks scary to me, doesn't that override other compiler flags?

Nope, I just built with it. If you don't provide CMake with a definition they're initialized to the empty string and all other flags are added by appending.

Well, I thought you create an option in the cmake script that creates the define with add_definitions if set. That's how its often done. Thereby it's implicitly documented.

Thus my comment above,

as far as arbitrary defines go, AFAICT you have to edit the makefiles to get it to work.

If this were a global debug flag and not a hyperspecific one with limited usability, that would make sense. Like I said, I'm not aware of any strictly followed conventions in this codebase for adding debugging code. So I'm open to suggestions.

@bagong
Copy link
Contributor

bagong commented Apr 24, 2017

Ah, the AFAICT read like "I am not sure..." to me, my fault.

I think a new block for in the top level CMakeLists.txt for debug stuff would be just fine. The file looks quite chaotic, but it does have blocks of stuff. And many of the individual entries are pretty peripheral... But I am not passionate with this...

@mossheim
Copy link
Contributor Author

I think a new block for in the top level CMakeLists.txt for debug stuff would be just fine.

One already exists.

@jamshark70
Copy link
Contributor

OK, thanks, I had kind of guess you could define it in the doc manager file, but I wasn't confident enough about that, and time is limited -- if I tried it and it didn't produce logging, I wouldn't have had time to investigate further.

Where, BTW, should this be documented for posterity? (Or, is it enough for long-time C programmers to see the ifdefs and know what to do?)

@mossheim
Copy link
Contributor Author

Where, BTW, should this be documented for posterity? (Or, is it enough for long-time C programmers to see the ifdefs and know what to do?)

The preprocessor is covered in most introductory C++ texts; you have to discuss it when talking about header file include guards. I am certainly not a long-time C programmer, and I've been coding regularly in C++ for less than a year.

Jeez, if I had known that adding debugging code for once would cause this much controversy, I would have just done my five-line commit and called it a day. I can either change the macro usage to NDEBUG, or add a commented-out #define before the macro to hint at the functionality, OR remove the macros altogether and print actual error messages when these commands fail, but I won't spend time documenting this anywhere outside the only file where it's relevant, which is the first file you'd look at if you were trying to debug the document manager anyway. If anyone is trying to fix a problem like this without actually opening the source, well, godspeed...

@jamshark70
Copy link
Contributor

Ok, sorry, I really didn't mean it to sound like that.

What I meant was, if someone builds from source but does not habitually read the source code, she wouldn't be aware that it's even possible to debug IDE <--> lang IPC. Such as myself... I saw the problem but I didn't know enough to go to the doc manager source.

But you're right, it's impossible to document everything. Some things do just have to be left for user questions.

@bagong
Copy link
Contributor

bagong commented Apr 25, 2017

Ok, sorry, I really didn't mean it to sound like that.

You didn't... ;)

Removed use of SC_DEBUG_DOC_MANAGER and replaced with the more
frequently used qWarning(), which behaves similarly to cerr.
I removed spaces from the output string because << for qWarning()
appends a space automatically.
@mossheim
Copy link
Contributor Author

Ok, using qWarning() now instead of cerr, and I got rid of the macro. So these messages will always post to stderr (not the post window) unless you've specifically built to disable Qt logging, which doesn't happen in any currently supported build mode.

@scztt
Copy link
Contributor

scztt commented Apr 25, 2017

The debug-only error reporting are probably an appropriate case for a runtime assert, which is a concept that SC should probably have and be using anyway. I mocked one up a while ago:
https://github.com/scztt/supercollider/tree/topic/line-numbers
https://github.com/scztt/supercollider/blob/topic/line-numbers/common/SC_Assert.h
https://github.com/scztt/supercollider/blob/topic/line-numbers/common/SC_Assert.cpp

So it would look something like:

} catch (std::exception const& e) {
    SC_ASSERT_MSG(false, std::string("DocumentManager could not handle request:") + e.what());
    return;
}

Not particularly important to introduce with this particular commit, but I think it's a pattern we need to introduce at some point.

@mossheim
Copy link
Contributor Author

mossheim commented May 7, 2017

I'm going to merge this now; it's a hotfix and can be amended later if need be.

@mossheim mossheim merged commit a3bdc7c into supercollider:master May 7, 2017
@mossheim mossheim deleted the topic/patch-set-doc-text-yaml-parsing branch May 7, 2017 14:42
@mossheim
Copy link
Contributor Author

mossheim commented May 7, 2017

@scztt I would totally be in favor of introducing more robust asserts, it would definitely be nice to have if/when I start to clean up some of the language backend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants