This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 123879 - IllegalArgumentException during parsing php script
Summary: IllegalArgumentException during parsing php script
Status: VERIFIED FIXED
Alias: None
Product: php
Classification: Unclassified
Component: Editor (show other bugs)
Version: 6.x
Hardware: All All
: P1 blocker (vote)
Assignee: Denis Anisimov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-12-12 13:07 UTC by Andrew Korostelev
Modified: 2008-02-05 12:44 UTC (History)
1 user (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
php script parsing failed with the following exception. (4.13 KB, text/plain)
2007-12-12 13:09 UTC, Andrew Korostelev
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Korostelev 2007-12-12 13:07:27 UTC
two IllegalArgumentExceptions occured during parsing of php file.
part of php editor functionality is blocked

  Product Version         = NetBeans IDE Dev (Build 200712120000)
  Operating System        = Windows XP version 5.1 running on x86
  Java; VM; Vendor        = 1.5.0_09; Java HotSpot(TM) Client VM 1.5.0_09-b03; Sun Microsystems Inc.

  PHP module version: built from sources 12.12.2007

steps:
- start NB with fresh user dir (with flag --userdir "<path>")
- create new php project 
- exceptions are rised on parsing created and opened php script.
Comment 1 Andrew Korostelev 2007-12-12 13:09:03 UTC
Created attachment 54190 [details]
php script parsing failed with the following exception.
Comment 2 Denis Anisimov 2007-12-18 16:52:35 UTC
This is problem in Languages module.
There was a recent changes at 06 Dec .
LanguageImpl class was added by Jan Jancura.
I think as result of this and related changes all our staff is broken .

I see the code in SLanguageProvider:
    public Language<STokenId> findLanguage (String mimeType) {
        if (LanguagesManager.getDefault ().isSupported (mimeType)) {
            try {
                org.netbeans.modules.languages.Language language = 
                    LanguagesManager.getDefault ().getLanguage (mimeType);
                if (language instanceof LanguageImpl)
                    new Listener ((LanguageImpl) language);
                if (language.getParser () == null)  return null;
                return new SLanguageHierarchy (language).language ();
            } catch (ParseException ex) {
            } catch (IllegalArgumentException ex) {
                // language is currently parsed
            }
        }
        return null;
    }

So findLanguage method returns null if parser is null.
But parser could be really null. So this is normal situation.
As result we get NULL language when trying to find embedded PHP language.
But this should not happens.

By the way I see a number of potential problems in other patrs of code:
method "public Token<STokenId> nextToken ()" in SLexer suggest that parser is not null and throw NPE 
when it called.

SLanguageHierarchy contains method that also throws NPE if parser is null.

Also please pay attention on this code in 
"public synchronized Language getLanguage (String mimeType) " of LanguagesManager class.

             RequestProcessor.getDefault ().post (new Runnable () {
                    public void run () {
                        try {
                            language.read ();
                        } catch (ParseException ex) {
                            Utils.message ("Editors/" + mimeType2 + "/language.nbs: " + ex.getMessage ());
                        } catch (IOException ex) {
                            Utils.message ("Editors/" + mimeType2 + "/language.nbs: " + ex.getMessage ());
                        }
                    }
                }, 2000);

As result "read()" method will be called in new thread.
But the latter method is called from "findLanguage (String mimeType)" method ( first method that I mentioned ).
And right away after this call you are trying to access to "getParser()" method .
I see here a number of problems : "read()" and "getParser()" are not syncronized. But they perform read/write access
to parser attribute from different thread.
And Such call sequence can obviously lead to null-ness result of getParser() method call in "findLanguage" impl.

Could you please fix these issues ?
Comment 3 Jan Jancura 2007-12-21 09:22:44 UTC
Sorry for slow response, but whole NetBeans team is on vacations this week.

IAE is fired because you are calling TokenHierarchy.create () method with langauge == null. You should check if
PhpTokenId.getPhpLanguage () is not null in PhpModelImpl:192.

SLanguageProvider.findLangauge (mimeType) returns null for given mime type, if the language is not registerred or
initialized.

org.netbeans.modules.languages.Langauge.getParser () returns null, if there is some langauge registerred for the
mimeType, but its not initialized yet. Thats because loading and parsing of nbs file is time consuming process, and it
should be done off line.

SLexer.nextToken () should not throw NPE, because Lexer is not created for language that is not initialized yet. The
same is true for LanguageHierarchy too.

So I do not see any issue on my side.
Comment 4 Denis Anisimov 2007-12-21 09:37:33 UTC
Please see my thoughts about this :
1) In the previous version all works fine.
2) As consequence of 1) PhpTokenId.getPhpLanguage() was not null in previous version.
3) PhpTokenId.getPhpLanguage() should not be null. 
Because I don't know other way how to get Language. 
Please provide me information how I can get not-null Language  
( as I already said in previous version all works fine and I didn't change anything ,
so I don't know the reason of current behavior ).
Why is it null ? Because I need some time for waiting ?
Is it true that after some time it will appears as not null ?

If no : so this is issue.
If yes :  why clients need to implement waiting logic on their side ?
I don't see any reasons to getting language in other thread and returning it as null 
if it was not yet initialized. Because I can't proceed further without Language reference.
So I need to implement waiting logic on my side. I think in all cases any usage 
of getting Language need access to not-null Language and each time they will need to wait.
So what is the purpose of such lazy init ?
Comment 5 Jan Jancura 2007-12-21 14:37:14 UTC
1-3) Yes, SLanguageProvider.findLangauge ("text/php") returns null, if PHP.nbs is not loaded. And it returns not null
value when PHP.nbs file is initialized. Its called lazy initialization. The purpose is performance. You should detect
this state and ignore it (like return empty parse tree, or whatever - I do not know exactly your usecase).

Question: "why clients need to implement waiting logic on their side ?" 
First, I am not sure if clients have to implement anything special in such case. In most cases you should just check
null value, and skip rest of code. Just return empty parse tree, or something similar. The most of functionality should
be untouched by this change. Your parser listener (or ASTEvaluator) is notified automatically when PHP.nbs file is
initialized.

Comment 6 Denis Anisimov 2007-12-24 10:29:37 UTC
Well, I understood current situation.
But in my case I need to implement waiting for language.
So lazy initialization in my case just additional complexity.
I cannot create PHP language without embedded language that is based on 
nbs file. But the latter language is lazy initialized after NB asking 
for top level language. So top level language need to wait when embedded
based in nbs file language will be loaded.

The option is writing language provider for top level language 
and lazy register it when embedded is registered but this even more complex then now.
Comment 7 Denis Anisimov 2007-12-24 10:30:40 UTC
Fixed via awaiting of initialization of embedded language.
Comment 8 kozlov 2008-02-05 12:44:17 UTC
Verified in build080131.