Rubberduck version information
The info below can be copy-paste-completed from the first lines of Rubberduck's log or the About box:
Rubberduck version 2.4.1.4627
Operating System: Win 10
Host Product: Microsoft Visual Basic 6.0
Description
It seems vb6 allows a semi colon on the Print line to suppress CRLF. It seems to be an exception but it is making parsing fail on my [very old and large] code base.
more info: https://stackoverflow.com/questions/9290731/what-is-the-effect-of-a-semicolon-at-the-end-of-a-line
Logfile
2019-04-02 16:40:03.7484;ERROR-2.4.1.4627;Rubberduck.Parsing.VBA.Parsing.ModuleParser;Syntax error; offending token ';' at line 746, column 21 in the CodePaneCode version of module modGeneral.;
2019-04-02 16:40:03.7484;DEBUG-2.4.1.4627;Rubberduck.Parsing.VBA.Parsing.ModuleParser;SyntaxErrorException thrown in thread 10, ParseTaskID f8b54930-1b42-4137-9da1-c1dfbab69269.;Rubberduck.Parsing.VBA.Parsing.ParsingExceptions.MainParseSyntaxErrorException: extraneous input ';' expecting {<EOF>, ':', REM, NEWLINE, ''', WS, LINE_CONTINUATION}
at Rubberduck.Parsing.VBA.Parsing.ParsingExceptions.MainParseExceptionErrorListener.SyntaxError(IRecognizer recognizer, IToken offendingSymbol, Int32 line, Int32 charPositionInLine, String msg, RecognitionException e) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\ParsingExceptions\MainParseExceptionErrorListener.cs:line 14
at Antlr4.Runtime.ProxyErrorListener`1.SyntaxError(IRecognizer recognizer, Symbol offendingSymbol, Int32 line, Int32 charPositionInLine, String msg, RecognitionException e)
at Antlr4.Runtime.Parser.NotifyErrorListeners(IToken offendingToken, String msg, RecognitionException e)
at Antlr4.Runtime.DefaultErrorStrategy.ReportUnwantedToken(Parser recognizer)
at Antlr4.Runtime.DefaultErrorStrategy.SingleTokenDeletion(Parser recognizer)
at Antlr4.Runtime.DefaultErrorStrategy.Sync(Parser recognizer)
at Rubberduck.Parsing.Grammar.VBAParser.endOfStatement() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 20219
at Rubberduck.Parsing.Grammar.VBAParser.block() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 2303
at Rubberduck.Parsing.Grammar.VBAParser.ifStmt() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 8893
at Rubberduck.Parsing.Grammar.VBAParser.mainBlockStmt() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 2707
at Rubberduck.Parsing.Grammar.VBAParser.blockStmt() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 2461
at Rubberduck.Parsing.Grammar.VBAParser.block() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 2302
at Rubberduck.Parsing.Grammar.VBAParser.subStmt() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 12721
at Rubberduck.Parsing.Grammar.VBAParser.moduleBodyElement() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 2238
at Rubberduck.Parsing.Grammar.VBAParser.moduleBody() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 2131
at Rubberduck.Parsing.Grammar.VBAParser.module() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 446
at Rubberduck.Parsing.Grammar.VBAParser.startRule() in C:\projects\rubberduck\Rubberduck.Parsing\obj\Release\net46\VBAParser.cs:line 334
at Rubberduck.Parsing.VBA.Parsing.VBATokenStreamParser.Parse(ITokenStream tokenStream, PredictionMode predictionMode, IParserErrorListener errorListener) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\VBATokenStreamParser.cs:line 21
at Rubberduck.Parsing.VBA.Parsing.TokenStreamParserBase.ParseLl(String moduleName, ITokenStream tokenStream, CodeKind codeKind) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\TokenStreamParserBase.cs:line 75
at Rubberduck.Parsing.VBA.Parsing.TokenStreamParserBase.ParseWithFallBack(String moduleName, CommonTokenStream tokenStream, CodeKind codeKind) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\TokenStreamParserBase.cs:line 52
at Rubberduck.Parsing.VBA.Parsing.TokenStreamParserBase.Parse(String moduleName, CommonTokenStream tokenStream, CodeKind codeKind, ParserMode parserMode) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\TokenStreamParserBase.cs:line 32
at Rubberduck.Parsing.VBA.Parsing.TokenStreamParserStringParserAdapterWithPreprocessing.Parse(String moduleName, String projectId, String code, CancellationToken token, CodeKind codeKind, ParserMode parserMode) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\TokenStreamParserStringParserAdapterWithPreprocessing.cs:line 29
at Rubberduck.Parsing.VBA.Parsing.ModuleParser.CodePanePassResults(QualifiedModuleName module, CancellationToken token, TokenStreamRewriter rewriter) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\ModuleParser.cs:line 165
at Rubberduck.Parsing.VBA.Parsing.ModuleParser.ParseInternal(QualifiedModuleName module, CancellationToken cancellationToken, TokenStreamRewriter rewriter, Guid taskId) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\ModuleParser.cs:line 84
at Rubberduck.Parsing.VBA.Parsing.ModuleParser.Parse(QualifiedModuleName module, CancellationToken cancellationToken, TokenStreamRewriter rewriter) in C:\projects\rubberduck\Rubberduck.Parsing\VBA\Parsing\ModuleParser.cs:line 40
Token: ; at L746C21
Kind of parsed code: CodePaneCode
Component: modGeneral (code pane version)
ParseType: Main parse
Additional context
Basically the line causing the issue is
obj.Print a$;
Thanks for the feedback! This parser bug has been reported as part of another issue last week - let's keep both open, and make the older one specific to the issue with Line statements.
ref. #4875
Ah I'm sorry - the title didn't give me any hints 馃槅
@mika76 no problem! we very much prefer having a single bug per issue, makes it easier to associate commits with a specific issue :smiley:
So I made a quick little DLL to try and see how the VBE actually works, made it COM-visible, exposing a Print method:

The Print member gets keyword syntax highlighting, which is a tell-tale sign something is going on at the language level. The code compiles, but running it throws run-time error 438 "member not found"; invoking PrintMethodTest.Class1.DoSomething correctly does nothing, as expected (implementations for both methods was left empty / no-op).
There is no apparent way to have a Print method that's an invokable member that doesn't support the trailing comma/semicolon shenanigans - not in user code (Sub Print() is illegal, Print is reserved), not in referenced type libraries.
Hence, seems we need to forbid Print as a member call, and special-case Print calls to support trailing comma/semicolons, regardless of what's qualifying them - not just Debug.
I'm not 100% but I think they can be separators as well as trailing. Both comma and semicolon
@mika76 that's correct - basically the parser rule we have for special-casing Debug.Print :+1:
@retailcoder Try implementing this IVBPrint interface on your test Class1
[
odl,
uuid(000204F0-0000-0000-C000-000000000046),
nonextensible
]
interface IVBPrint : IUnknown {
HRESULT _stdcall WriteText([in] BSTR strText);
[propput]
HRESULT _stdcall Column([in] long retVal);
[propget]
HRESULT _stdcall Column([out, retval] long* retVal);
};
I'm very curious too if this works. . .
Error 438 Member not found is the wrong way to say IVBPrint interface not found :-))
Interesting. Never have seen IVBPrint interface before. In where is it defined?
On Access where Print with comma/semicolon works on an Access.Report object, the OLE viewer does not show it having that interface.
I'm not sure its documented and I don't have it in my HKLM\Classes\Interface too.
Its IID is in pretty system family of IIDs:
{00020400-0000-0000-C000-000000000046} IDispatch
{00020401-0000-0000-C000-000000000046} ITypeInfo
{00020402-0000-0000-C000-000000000046} ITypeLib
{00020403-0000-0000-C000-000000000046} ITypeComp
{00020404-0000-0000-C000-000000000046} IEnumVARIANT
. . .
Second result of google search by its IID is where I got it from.
I guess this is the 2nd result of google search (It was 4th for me)
VBForums hijacking psuedomethods
Interesting -- apparently Circle/Pset/Print/etc. pseudo methods are in fact just a bunch of APIs under the hood. The link had a side discussion about how to override the Circle method and provide custom behavior.
That also means we can in theory check whether a call to Print is valid by checking if the type implements the undocumented interface.
Try implementing this IVBPrint interface on your test Class1
Just as a FYI - this seems to be documented now
Hey @retailcoder this is great stuff! Any idea when your next stable release will be? Last one was in march...
The current plan is early to mid November.
@MDoerner fantastic thanks!