multilanguage kdevelop

David Nolden zwabel at
Thu Jul 29 13:01:15 UTC 2010

2010/7/29 Milian Wolff <mail at>:
> On Thursday, 29. July 2010 01:09:09 David Nolden wrote:
>> >From what I see, the context doesn't have any members. You could add
>> an "IndexedString language()" member, and then put that thing into
>> kdevplatform as "LanguageTopDUContext" or something like that (after
>> all it's the top-context of the language).
>> Regarding updating: The "setEncountered" thing doesn't look nice.
>> Couldn't you just share the same "encountered" cache across all
>> context-builders? You could create a class like
>> namespace KDevelop {
>> struct ParseSession {
>>   bool m_valid;
>>   SimpleRange m_range;
>>   QSet<DUChainBase*> m_encountered;  // or whatever other
>> data-structure we use currently
>>   ParseJob::Contents m_contents;
>>   DUContext* m_updating;
>>   // Add here whatever else would be needed across different languages
>> };
>> };
>> And then, you could do something like this:
>> // We encounter a something that contains a different language than
>> what we're parsing now
>> void parseSubLanguageContext(AST* subLanguageAST)
>> {
>> ParseSession subSession;
>> subSession.m_valid = true;
>> subSession.m_range = rangeFromAST(subLanguageAST);
>> subSession.m_contents = m_contents;
>> subSession.m_encountered = m_encountered;
>> subSession.m_updating = createContext(subLanguageAST);
>> ILanguageSupport* langSupport = languageFromAST(subLanguageAST);
>> if(langSupport)
>>  {
>>   ParseJob* job = langSupport->createParseJob(subSession);
>>   job->parseForeground();
>>   m_encountered = subSession.m_encountered;
>>  }
>> }
> This does not work as I have reported before. The parsing is done in the
> background but the language might not be loaded at that point, and loading a
> LangPlugin from the background is explicitly forbidden.

But it can be done anyway. As long as you don't hold any locks in the
background, you can send an event to the foreground to load the
language-support there. Unfortunately the DO_IN_FOREGROUND macros I
added to foregroundlock.h don't work yet, but you could simply add a
function "void loadLanguageFromBackground(QString language);" and a
slot "void loadLanguageInternal(QString language);" to
LanguageController, and in loadLanguageFromBackground simply do
"QMetaObject::invokeMethod(this, "loadLanguageInternal",
Q_ARG(QString, myLanguage), Qt::QueuedBlockingConnection);".
loadLanguageFromBackground would return only _after_ the language was
loaded in the foreground, and thus could be used to load
language-supports from the background. Just make sure that you hold no
locks/mutexes while doing that.

> That is why I jumped through hoops with the background parser.
> Still, your code above looks much nicer than what I have so if you have any
> idea on how to circumvent this hurdle I'm all for it.
> I'll still try to use your idea with ParseSession to get the DUChainBase stuff
> in. But the problem there would be (with the current approach using the
> BackgroundParser) that the DUChainBase* items might get invalidated, right?
> I'd have to use some Refcounted pointer like the DeclarationPointer, right?
> Hmm...

I don't understand what you mean by that invalidation. You can have a
safe weak-pointer to a DUChainBase* through DUChainPointer (it's
nearly the same as DeclarationPointer). However it should not be
possible that an item that you're currently parsing is invalidated by
something else (for example UrlParseLock prevents that in C++).

Sorry, I have no time at the moment to look at your code directly.
Using the background-parser could work as well, but it would be hard
and ugly to pass all the information through the whole scheduling code
of the background-parser. It would be much better to use the
parse-jobs directly bypassing the background-parser, as the whole
scheduling of the background-parser isn't required. After all you want
the parsing to be done _now_ and in the current thread.

Greetings, David

More information about the KDevelop-devel mailing list