<div dir="ltr"><div class="gmail_default" style=""><font face="monospace">Hi everyone,</font></div><div class="gmail_default" style=""><font face="monospace"><br>Here is the updated master information table file.<br>I haven't marked the poc 3,4,5 in this.</font></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Fri, 11 Jul 2025 at 19:58, Devansh Varshney <<a href="mailto:varshney.devansh614@gmail.com">varshney.devansh614@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div style="color:rgb(204,204,204);background-color:rgb(31,31,31);font-size:12px;line-height:18px;white-space:pre-wrap"><div style="font-family:Menlo,Monaco,"Courier New",monospace"><span style="font-family:monospace">Hi everyone,</span></div><font face="monospace"><br><br></font><div><font face="monospace"> This week marks a major turning point. After fixing the critical UI stability</font></div><div><font face="monospace"> issues in Week 6, we tackled the core challenge of populating our Object</font></div><div><font face="monospace"> Browser with live data. The journey led to a fundamental "aha!" moment about</font></div><div><font face="monospace"> how UNO's reflection system works, forcing a complete architectural rethink</font></div><div><font face="monospace"> of our data provider.</font></div><font face="monospace"><br></font><div><font face="monospace"> The result is a resounding success. We now have a stable, responsive Object</font></div><div><font face="monospace"> Browser that correctly populates the entire UNO API hierarchy on demand,</font></div><div><font face="monospace"> resolving the crashes and discovery issues that blocked us previously.</font></div><font face="monospace"><br><br></font><div><font face="monospace"> Gerrit Patch: <a href="https://gerrit.libreoffice.org/c/core/+/186822" target="_blank">https://gerrit.libreoffice.org/c/core/+/186822</a></font></div><font face="monospace"><span class="gmail_default" style="font-family:"comic sans ms",sans-serif"> </span><span class="gmail_default"> Screen Shot Image: </span><a href="https://bug-attachments.documentfoundation.org/attachment.cgi?id=201757" target="_blank">https://bug-attachments.documentfoundation.org/attachment.cgi?id=201757</a><br><br><br></font><div><font face="monospace"> <b> == The Great Discovery Debate: A Flawed Assumption ==</b></font></div><font face="monospace"><br><br></font><div><font face="monospace"> My initial approach to populating the UNO API tree was intuitive but, as it</font></div><div><font face="monospace"> turned out, fundamentally flawed. I assumed we could "discover" the API</font></div><div><font face="monospace"> hierarchically, making live API calls for each level of the tree as the</font></div><div><font face="monospace"> user expanded it.</font></div><font face="monospace"><br></font><div><font face="monospace"> <b>*The Flawed "Live Discovery" Flow:*</b></font></div><font face="monospace"><br><br></font><div><font face="monospace">+----------------------------------------------------------------------------+</font></div><div><font face="monospace">| [User expands "UNO APIs"] -> Calls GetChildNodes("") |</font></div><div><font face="monospace">| | |</font></div><div><font face="monospace">| v |</font></div><div><font face="monospace">| +------------------------------------------------------------------------+ |</font></div><div><font face="monospace">| | GetChildren("") | |</font></div><div><font face="monospace">| | - SUCCESS: Returns hardcoded list: ["com", "org"] | |</font></div><div><font face="monospace">| +------------------------------------------------------------------------+ |</font></div><div><font face="monospace">| | |</font></div><div><font face="monospace">| [User expands "com"] -> Calls GetChildNodes("com") |</font></div><div><font face="monospace">| | |</font></div><div><font face="monospace">| v |</font></div><div><font face="monospace">| +------------------------------------------------------------------------+ |</font></div><div><font face="monospace">| | GetChildren("com") | |</font></div><div><font face="monospace">| | - Queries UNO API with "com". | |</font></div><div><font face="monospace">| | - API returns an object, but *not* a list of child names. | |</font></div><div><font face="monospace">| | - The check fails, an empty list is returned. | |</font></div><div><font face="monospace">| | - RESULT: Tree expansion stops. -> BUG! | |</font></div><div><font face="monospace">| +------------------------------------------------------------------------+ |</font></div><div><font face="monospace">+----------------------------------------------------------------------------+</font></div><font face="monospace"><br></font><div><font face="monospace"> This approach, using <b>XHierarchicalNameAccess::getByHierarchicalName</b>,</font></div><div><font face="monospace"> failed because the UNO reflection API is optimized for</font></div><div><font face="monospace"> Introspection (looking up a known, fully-qualified name), not for</font></div><div><font face="monospace"> hierarchical Discovery (browsing the contents of a partial path).</font></div><div><font face="monospace"> We were trying to ask the city for a list of all streets,</font></div><div><font face="monospace"> then ask each street for a list of all buildings—a process</font></div><div><font face="monospace"> that is inefficient and not directly supported.</font></div><font face="monospace"><br><br><br><br></font><div><font face="monospace"><b> == The "Aha!" Moment: The Correct Architecture ==</b></font></div><font face="monospace"><br><br></font><div><font face="monospace"> The breakthrough came from re-reading Stephan's crucial clarification on the</font></div><div><font face="monospace"> roles of the TypeManager and ServiceManager.</font></div><font face="monospace"><br><br></font><div><font face="monospace"> - ServiceManager: For component implementations.</font></div><div><font face="monospace"> - TypeManager: For all UNOIDL entity descriptions (types, services,</font></div><div><font face="monospace"> modules, etc.).</font></div><font face="monospace"><br></font><div><font face="monospace"> This clarified everything. The TypeManager holds the descriptions of</font></div><div><font face="monospace"> everything in the UNO API.</font></div><div><font face="monospace"> We cannot efficiently "discover" the tree live. Instead, we must first build</font></div><div><font face="monospace"> a map of the entire city and then use that map to guide the user.</font></div><font face="monospace"><br><br></font><div><font face="monospace"> This led to a complete redesign of the IdeDataProvider to use a hybrid</font></div><div><font face="monospace"> approach: a one-time cache for discovery, and live introspection for details.</font></div><font face="monospace"><br></font><div><font face="monospace"> <b>The New, Correct Data Flow:</b></font></div><font face="monospace"><br><br></font><div><font face="monospace"> +------------------------------------------------------------------+</font></div><div><font face="monospace"> | PHASE 1: ONE-TIME CACHE CREATION (in IdeDataProvider constructor)|</font></div><div><font face="monospace"> +------------------------------------------------------------------+</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> | [1] Get the TypeDescriptionManager singleton. |</font></div><div><font face="monospace"> | ...getValueByName("...theTypeDescriptionManager") |</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> | [2] Create an enumeration for ALL UNO entities. |</font></div><div><font face="monospace"> | ...createTypeDescriptionEnumeration(..., INFINITE) |</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> | [3] Loop through the flat list of ~20,000 descriptions. |</font></div><div><font face="monospace"> | while (xEnum->hasMoreElements()) |</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> | [4] For each description, parse its full name (e.g., |</font></div><div><font face="monospace"> | "com.sun.star.sheet.XSpreadsheet") and use addNode to |</font></div><div><font face="monospace"> | build a tree structure inside our m_hierarchyCache map. |</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> | (This entire process takes ~0.9s and happens only once.) |</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> +------------------------------------------------------------------+</font></div><div><font face="monospace"> |</font></div><div><font face="monospace"> v</font></div><div><font face="monospace"> +------------------------------------------------------------------+</font></div><div><font face="monospace"> | PHASE 2: LIVE UI INTERACTION |</font></div><div><font face="monospace"> +------------------------------------------------------------------+</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> | [User expands "com.sun.star" in the TreeView] |</font></div><div><font face="monospace"> | | |</font></div><div><font face="monospace"> | v |</font></div><div><font face="monospace"> | [A] GetChildNodes("com.sun.star") is called. |</font></div><div><font face="monospace"> | - It performs an instant O(log N) lookup in our |</font></div><div><font face="monospace"> | m_hierarchyCache map. |</font></div><div><font face="monospace"> | - Returns the cached list of children (e.g., "sheet"). |</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> | [User selects "XSpreadsheet" in the TreeView] |</font></div><div><font face="monospace"> | | |</font></div><div><font face="monospace"> | v |</font></div><div><font face="monospace"> | [B] GetMembers("...XSpreadsheet") is called. |</font></div><div><font face="monospace"> | - It performs a live introspection call. |</font></div><div><font face="monospace"> | - theCoreReflection->forName("...XSpreadsheet") |</font></div><div><font face="monospace"> | - This is fast and gets the rich member details. |</font></div><div><font face="monospace"> | |</font></div><div><font face="monospace"> +------------------------------------------------------------------+</font></div><font face="monospace"><br></font><div><font face="monospace"> This hybrid model gives us the best of both worlds: a fast, responsive UI</font></div><div><font face="monospace"> for browsing, and detailed, live information when the user needs it.</font></div><font face="monospace"><br><br><br><br></font><div><font face="monospace"><b> == Q&A: The Architectural Deep Dive ==</b></font></div><font face="monospace"><br><br></font><div><font face="monospace"> This new design was a deliberate choice based on our findings, and it's</font></div><div><font face="monospace"> worth clarifying the key principles.</font></div><font face="monospace"><br><br></font><div><font face="monospace"> <b>Q1: How does this reconcile with mentors saying "live fetching is not slow"?</b></font></div><font face="monospace"><br></font><div><font face="monospace"> A: The mentors were absolutely right, but we were misapplying the advice.</font></div><div><font face="monospace"> They were referring to Introspection (getting members of a single, known</font></div><div><font face="monospace"> type like XSpreadsheet), which our GetMembers function now does, and it</font></div><div><font face="monospace"> is very fast. Our initial error was trying to use a live API for</font></div><div><font face="monospace"> hierarchical Discovery, which is the part that is not directly supported</font></div><div><font face="monospace"> or performant. We now use the cache for discovery and live queries for</font></div><div><font face="monospace"> introspection.</font></div><font face="monospace"><br><br></font><div><font face="monospace"> <b>**Q2: What is this "session cache" and how does it differ from the long-term</b></font></div><div><font face="monospace"><b> IdeCodeCompletionCache vision?**</b></font></div><font face="monospace"><br></font><div><font face="monospace"> A: The cache we built this week is a session cache. It's a</font></div><div><font face="monospace"> std::map<OUString, SymbolInfoList> that lives only as long as the</font></div><div><font face="monospace"> IdeDataProvider instance. Its purpose is to solve the immediate functional</font></div><div><font face="monospace"> problem of making the UNO API browsable.</font></div><font face="monospace"><br></font><div><font face="monospace"> The long-term IdeCodeCompletionCache is a future goal for a **persistent</font></div><div><font face="monospace"> cache**. The logic we wrote to build our session cache could one day be run</font></div><div><font face="monospace"> during the LibreOffice build process to create a static file (e.g., SQLite)</font></div><div><font face="monospace"> that ships with the product. This would make startup even faster, as we'd be</font></div><div><font face="monospace"> loading a pre-computed tree instead of building it at runtime. Our current</font></div><div><font face="monospace"> work is the perfect prototype for that future system.</font></div><font face="monospace"><br><br></font><div><font face="monospace"> <b> Q3: What was the final `Reference.h` crash about?</b></font></div><font face="monospace"><br></font><div><font face="monospace"> A: With the new data provider working, a final bug emerged: a crash when</font></div><div><font face="monospace"> selecting com.sun.star.beans.Ambiguous. Digging into the IDL file, I found</font></div><div><font face="monospace"> it's a generic template (struct Ambiguous<T>). Our code was too optimistic;</font></div><div><font face="monospace"> when introspecting this template, the reflection API would sometimes return</font></div><div><font face="monospace"> a NULL Reference<> for fields whose type depended on the unspecified</font></div><div><font face="monospace"> template parameter T. The fix was to make our code more defensive by adding</font></div><div><font face="monospace"> if (!xField.is()) and if (!xMethod.is()) checks in</font></div><div><font face="monospace"> ImplGetMembersOfUnoType, which has made the browser completely stable.</font></div><font face="monospace"><br><br><br></font><div><font face="monospace"><b> == Current Status & Next Steps ==</b></font></div><font face="monospace"><br><br></font><div><font face="monospace"> The Object Browser is now functional and stable. The left-hand tree populates</font></div><div><font face="monospace"> correctly with identifying prefixes ([n], [I], [S], etc.), and the</font></div><div><font face="monospace"> right-hand pane shows the live members of any selected UNO entity.</font></div><font face="monospace"><br></font><div><font face="monospace"> With this solid foundation, we can now proceed with confidence:</font></div><font face="monospace"><br><br></font><div><font face="monospace"> - Immediate Next Step: Implement the right-hand members pane as a</font></div><div><font face="monospace"> TreeView with categories ("Properties", "Methods", "Events") to match</font></div><div><font face="monospace"> our design mockup.</font></div><div><font face="monospace"> - Then: Implement the bottom information pane to show the full</font></div><div><font face="monospace"> signature of the selected member.</font></div><font face="monospace"><br><br></font><div><font face="monospace"> This week was a huge leap forward, validating our architecture and unblocking</font></div><div><font face="monospace"> the path to a feature-complete Object Browser.</font></div><font face="monospace"><br></font><div><font face="monospace"> Thanks for all the guidance and feedback that got us to this point.</font></div><div style="color:rgb(204,204,204);background-color:rgb(31,31,31);font-size:12px;line-height:18px;white-space:pre-wrap"><font face="monospace"><br></font></div><div style="color:rgb(204,204,204);background-color:rgb(31,31,31);font-size:12px;line-height:18px;white-space:pre-wrap"><font face="monospace"><br></font></div><div><div class="gmail_default"><div style="font-family:Menlo,Monaco,"Courier New",monospace;line-height:18px"><div> I have also added a txt file in case the diagrams format went off direction.</div><br><br><div> Week 1 mail -</div><div> <a href="https://lists.freedesktop.org/archives/libreoffice/2025-May/093264.html" target="_blank">https://lists.freedesktop.org/archives/libreoffice/2025-May/093264.html</a></div><br><div> Week 2 and 3 mail -</div><div> <a href="https://lists.freedesktop.org/archives/libreoffice/2025-June/093362.html" target="_blank">https://lists.freedesktop.org/archives/libreoffice/2025-June/093362.html</a></div><br><div> Week 4 mail(Thread) -</div><div> <a href="https://lists.freedesktop.org/archives/libreoffice/2025-June/093392.html" target="_blank">https://lists.freedesktop.org/archives/libreoffice/2025-June/093392.html</a></div><br><div> Week 5 mail -</div><div> <a href="https://lists.freedesktop.org/archives/libreoffice/2025-June/093443.html" target="_blank">https://lists.freedesktop.org/archives/libreoffice/2025-June/093443.html</a></div><br><div> week 6 mail - </div><div> <a href="https://lists.freedesktop.org/archives/libreoffice/2025-July/093493.html" target="_blank">https://lists.freedesktop.org/archives/libreoffice/2025-July/093493.html</a></div></div></div></div><font face="Menlo, Monaco, Courier New, monospace"><br></font><div style="font-family:Menlo,Monaco,"Courier New",monospace"><br></div></div></div><div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><span style="font-family:monospace"><b>Regards,</b></span></div><div><span style="font-family:monospace;color:rgb(153,0,255)"><b>Devansh</b></span><br></div></div></div></div>
</blockquote></div><div><br clear="all"></div><div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><span style="font-family:monospace"><b>Regards,</b></span></div><div><span style="font-family:monospace;color:rgb(153,0,255)"><b>Devansh</b></span><br></div></div></div>