[Monodevelop-devel] Rethinking the IDocumentMetaInformation

Michael Hutchinson m.j.hutchinson at gmail.com
Wed Sep 10 13:46:19 EDT 2008


On Wed, Sep 10, 2008 at 6:10 AM, Mike Krüger <mkrueger at novell.com> wrote:
> Hi
>
>> Hi,
>>
>> I'm confused about the purpose of the IDocumentMetaInformation:
>>
>> <mkrueger> @mhutch: you one complained that it was in the parser :)
>> <mkrueger> therefore I put it into another part
>>
>> My exact complaint was that I had to use an ICompilationUnit to mark
>> folding region and errors, and that it contained a lot of
>> .NET-specific information which i didn't need. However, I did
>> implement that for ASP.NET and it works fine... The
>> IDocumentMetaInformation does not fix this at all.
>>
>
> It does fix it that way that .NET specific information is not
> in IDocumentMetaInformation.

True, but it wasn't possible to use the IDocumentMetaInformation
without an ICompilationUnit too. Also, the  IDocumentMetaInformation
was missing some functionality (in particular, errors), and folding
regions were duplicated across both.

>> Worse, it requires a second parse and isn't stored is a publicly
>> shared location, so has to be reparsed by e.g. the document outline
>> provider, which requires the #region locations. Also, text editor only
>> parses an IDocumentMetaInformation when a CompilationUnit appears, so
>> a CompilationUnit has to be generated anyway!
>>
>
> Thats because of the mcs stuff. It requires a second parse of the file,
> because it doesn't give me information about regions, comments etc.

That's an implementation detail specific to the mcs-based parser, so
should not affect core interfaces if we can avoid it.

> My long term vision for that was that a delta parser should take care of
> teh document meta information. The meta information should consists only
> on stuff that are regular expressions.

Couldn't an incremental/delta parser be used to /update/ the
CompilationUnit? At this point we don't even know if/how an
incremental parser could be implemented, so it seems premature to
design around it. This also seems rather mcs-specific.

>> I have some suggestions for a solution.
>>
>> I suggest we have the IParser instead return an IParsedDocument, which
>> would be very generic, with the basic info used by the text editor:
>>
> 
>> IParsedDocument
>> {
>>     string FileName;
>>     DateTime ParseTime { get; }
>>     IEnumerable<Fold> GetFoldLocations ();   //expected to iterate
>> over types, comments etc and generate folds
>>     ICollection<Error> Errors { get; } //also warnings
>>     bool HasErrors { get; }
>> }
>>
>> There would then be an ICompilationUnit derived interface, with
>> generic info for things like the quick finder and document outline.
>>
> 
>> ICompilationUnit : IParsedDocument
>> {
>>     ICollection<IBaseType> Types { get; }
>>     ICollection<IBaseMember> GlobalMembers { get; }
>> 
>>     IEnumerable<Comment> Comments { get; }
>> }
>>
>> The .NET info would be in the derived ICompilationUnit, and would be
>> returned by .NET parsers:
>>
> 
>> IDotNetCompilationUnit : ICompilationUnit
>> {
>>     ICollection<IUsing> Usings { get; }
>>     ICollection<IAttribute> Attributes { get; }
>>     ICollection<IType> Classes { get; }   // foreach (IBaseType t in
>> Types) yield return (IType) t;
>>     ICollection<Coderegion> CodeRegions { get; }   //#regions
>> }
>>
>> Even better, this moves some generic logic out of the SourceEditor2,
>> so that the compilationunit / parseddocument could control the fold
>> locations, i.e. GetFoldLocations () would generate regions by
>> iterating over the members, classes, comments, C #regions, etc.

This is one of the important points in my proposal, since IMO we have
been hardcoding too much .NET-specific functionality into
SourceEditor2 is a way that is not extensible/overridable.

>> I could implement an AspNetDocument : IParsedDocument. The C/C++
>> parser could return a CCompilationUnit : ICompilationUnit
>>
>> Does this sound like a good plan? Should I implement it?
>>
>
> Hm, I think that'll produce too many upcasts only for different levels
> of information.

Why are the upcasts a problem? They are all designed/intended to be
used in different ways.

> Something like this should work better:
> 
> IParsedDocument
> {
>    string FileName;
>
>    DateTime ParseTime { get; }
>
>    IEnumerable<Fold> FoldLocations { get };  // expected to iterate
> over types, comments etc and generate folds
>
>    ICollection<Error> Errors { get; }        // also warnings
>    bool HasErrors { get; }
> 
>    IEnumerable<Comment> Comments { get; }
> 
>    ICollection<Coderegion> CodeRegions { get; }   //#regions
>
>    ICompilationUnit CompilationUnit { get; }
> }
> 
> ICompilationUnit
> {
>    ICollection<IUsing> Usings { get; }
>    ICollection<IAttribute> Attributes { get; }
>    ICollection<IType> Classes { get; }   // foreach (IBaseType t in
> Types) yield return (IType) t;
> }
>
> Then'll don't need to upcast every time.
>
> Regards
> Mike
>
>

I've looked at your changes in SVN, and I'm not totally happy; it
would have been nice to finish the discussion first. At least it's a
step in the right direction.

My concerns are:
* Still not generic enough -- .NET-centric: ConditionalRegion,
PreProcessorDefine, ICompilationUnit will not be needed for many
languages, and are not things that the text editor will use.
* Not designed around use cases -- for example, things like the quick
finder and document outline will still be tied to .NET. IMO the
ParseDocument should be "decomposable" into different interfaces for
different purposes, i.e. text editor's errors&folding, quick
finder/outline showing structure, .NET completion DB information, etc.
Only a single upcast would be required for any one purpose.
* Still leaves ICompilationUnit->folds mapping code in the
SourceEditor2. I'd like the ParseDocument to be able to perform this
mapping so that it can be overridden.

-- 
Michael Hutchinson
http://mjhutchinson.com


More information about the Monodevelop-devel-list mailing list