Skip to content

Commit

Permalink
Feat: Store include file uris in the analyzed document for querying i…
Browse files Browse the repository at this point in the history
…nfo by them
  • Loading branch information
WilsonZiweiWang committed Dec 22, 2023
1 parent d43c3ff commit 627129e
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 18 deletions.
6 changes: 3 additions & 3 deletions server/src/__tests__/analyzer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ describe('sourceIncludeFiles', () => {

const fsReadFileSyncMock = jest.spyOn(fs, 'readFileSync')

analyzer.sourceIncludeFiles(uri, [], {})
analyzer.sourceIncludeFiles(uri, [], [])

expect(fsReadFileSyncMock).toHaveBeenCalledWith(FIXTURE_URI.DIRECTIVE.replace('file://', ''), 'utf8')
expect(fsReadFileSyncMock).toHaveBeenCalledWith(FIXTURE_URI.FOO_INC.replace('file://', ''), 'utf8')
Expand Down Expand Up @@ -240,7 +240,7 @@ describe('sourceIncludeFiles', () => {

const loggerMock = jest.spyOn(logger, 'debug')

analyzer.sourceIncludeFiles(uri, [], {})
analyzer.sourceIncludeFiles(uri, [], [])

let loggerDebugCalledTimes = 0
loggerMock.mock.calls.forEach((call) => {
Expand Down Expand Up @@ -274,7 +274,7 @@ describe('sourceIncludeFiles', () => {

/* eslint-disable-next-line prefer-const */
let symbols: GlobalDeclarations[] = []
analyzer.sourceIncludeFiles(uri, symbols, {})
analyzer.sourceIncludeFiles(uri, symbols, [])

expect(symbols).toEqual(
expect.arrayContaining([
Expand Down
13 changes: 12 additions & 1 deletion server/src/connectionHandlers/onHover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,24 @@ function getGlobalSymbolComments (uri: string, word: string): string | null {
if (analyzer.getGlobalDeclarationSymbols(uri).some((symbol) => symbol.name === word)) {
const analyzedDocument = analyzer.getAnalyzedDocument(uri)
const symbolComments = analyzedDocument?.globalSymbolComments
const includeFileUris = analyzedDocument?.includeFileUris
if (symbolComments === undefined) {
return null
}
if (symbolComments[word] !== undefined) {
const allCommentsForSymbol = symbolComments[word]
const localCommentsForSymbol = symbolComments[word]

const otherCommentsForSymbol: GlobalSymbolComments[string] = []
includeFileUris?.forEach((includeFileUri) => {
const analyzedDocumentForIncludeFile = analyzer.getAnalyzedDocument(includeFileUri)
const symbolCommentsForIncludeFile = analyzedDocumentForIncludeFile?.globalSymbolComments
if (symbolCommentsForIncludeFile !== undefined) {
otherCommentsForSymbol.push(...(symbolCommentsForIncludeFile[word] ?? []))
}
})
const priority = ['.bbclass', '.conf', '.inc', '.bb', '.bbappend']

const allCommentsForSymbol = [...localCommentsForSymbol, ...otherCommentsForSymbol]
let commentsToShow: GlobalSymbolComments[string] = []
// higher priority comments replace lower ones
priority.reverse().forEach((ext) => {
Expand Down
30 changes: 16 additions & 14 deletions server/src/tree-sitter/analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface AnalyzedDocument {
globalDeclarations: GlobalDeclarations
globalSymbolComments: GlobalSymbolComments
embeddedRegions: EmbeddedRegions
includeFileUris?: string[]
tree: Parser.Tree
extraSymbols?: GlobalDeclarations[] // symbols from the include files
}
Expand Down Expand Up @@ -77,14 +78,19 @@ export default class Analyzer {
const tree = this.parser.parse(fileContent)
const [globalDeclarations, globalSymbolComments] = getGlobalDeclarationsAndComments({ tree, uri })
const embeddedRegions = getEmbeddedRegionsFromNode(tree, uri)
/* eslint-disable-next-line prefer-const */

// eslint-disable-next-line prefer-const
let extraSymbols: GlobalDeclarations[] = []
this.sourceIncludeFiles(uri, extraSymbols, globalSymbolComments, { td: document, tree })
// eslint-disable-next-line prefer-const
let includeFileUris: string[] = []
this.sourceIncludeFiles(uri, extraSymbols, includeFileUris, { td: document, tree })

this.uriToAnalyzedDocument[uri] = {
document,
globalDeclarations,
globalSymbolComments,
embeddedRegions,
includeFileUris,
tree,
extraSymbols
}
Expand Down Expand Up @@ -456,7 +462,7 @@ export default class Analyzer {
* @param uri
* @param document Main purpose of this param is to avoid re-reading the file from disk and re-parsing the tree when the file is opened for the first time since the same process will happen in the analyze() before calling this function.
*/
public sourceIncludeFiles (uri: string, extraSymbols: GlobalDeclarations[], globalSymbolComments: GlobalSymbolComments, document?: { td: TextDocument, tree: Parser.Tree }): void {
public sourceIncludeFiles (uri: string, extraSymbols: GlobalDeclarations[], includeFileUris: string[], document?: { td: TextDocument, tree: Parser.Tree }): void {
if (this.parser === undefined) {
logger.error('[Analyzer] The analyzer is not initialized with a parser')
return
Expand All @@ -470,7 +476,6 @@ export default class Analyzer {
textDocument = document.td
parsedTree = document.tree
} else {
let globalSymbolCommentsForIncludeFile: GlobalSymbolComments
const analyzedDocument = this.uriToAnalyzedDocument[uri]
let globalDeclarations: GlobalDeclarations
if (analyzedDocument === undefined) {
Expand All @@ -483,12 +488,11 @@ export default class Analyzer {
parsedTree = this.parser.parse(textDocument.getText())
// Store it in analyzedDocument just like what analyze() does to avoid re-reading the file from disk and re-parsing the tree when editing on the same file
globalDeclarations = getGlobalDeclarationsAndComments({ tree: parsedTree, uri })[0]
globalSymbolCommentsForIncludeFile = getGlobalDeclarationsAndComments({ tree: parsedTree, uri })[1]

this.uriToAnalyzedDocument[uri] = {
document: textDocument,
globalDeclarations,
globalSymbolComments: globalSymbolCommentsForIncludeFile,
globalSymbolComments: getGlobalDeclarationsAndComments({ tree: parsedTree, uri })[1],
embeddedRegions: getEmbeddedRegionsFromNode(parsedTree, uri), // TODO: Avoid doing this operation as it is not needed during the sourcing process
tree: parsedTree
}
Expand All @@ -497,21 +501,19 @@ export default class Analyzer {
textDocument = analyzedDocument.document
parsedTree = analyzedDocument.tree
globalDeclarations = analyzedDocument.globalDeclarations
globalSymbolCommentsForIncludeFile = analyzedDocument.globalSymbolComments
}
extraSymbols.push(globalDeclarations)
// Merge the variables exist in both globalSymbolCommentsForIncludeFile and globalSymbolComments
Object.keys(globalSymbolCommentsForIncludeFile).forEach((key) => {
if (globalSymbolComments[key] !== undefined) {
globalSymbolComments[key] = globalSymbolComments[key].concat(globalSymbolCommentsForIncludeFile[key])
}
})
}

// Recursively scan for files in the directive statements `inherit`, `include` and `require` and pass the same reference of extraSymbols to each recursive call
const fileUris = this.getDirectiveFileUris(parsedTree)
fileUris.forEach(uri => {
if (!includeFileUris.includes(uri)) {
includeFileUris.push(uri)
}
})
for (const fileUri of fileUris) {
this.sourceIncludeFiles(fileUri, extraSymbols, globalSymbolComments, undefined)
this.sourceIncludeFiles(fileUri, extraSymbols, includeFileUris, undefined)
}
} catch (error) {
if (error instanceof Error) {
Expand Down

0 comments on commit 627129e

Please sign in to comment.