function buildIntelliSenseModels() {


        let chartObjectPrefix = 'chart.'
        let marketPrefix = 'market.'
        let exchangePrefix = 'exchange.'
        let dot = '.'
        let numberOfPreviousSuffixes = 5

        UI.projects.workspaces.spaces.designSpace.workspace.workspaceNode.rootNodes.forEach(node => {
            if (node.type === 'Data Mine') {
                // Getting all the Javascript code nodes into one single model
                UI.projects.visualScripting.utilities.branches.nodeBranchToArray(node, 'Procedure Javascript Code').forEach(node => {
                    codeString += '\n'
                    codeString += node.code
                })

                /**
                 * Generating an object represantation for "chart" object autocomplete
                 * The logic is inspired by the condition editor
                 * First we create a string representation with "." notation e.g: chart.at24hs.candlesChannel.begin for all the data mines and their bots in the workspace
                 * Secondly we are going to convert all the strings to an object which will be used by the editor to predict possible values
                 * e.g : we will end with something like {
                 *     chart: {
                 *         at24hs: {
                 *              candlesChannel: {
                 *                  begin: "",
                 *                  direction: "",
                 *                  end: "",
                 *                  period: ""
                 *              },
                 *              previous: {...},
                 *              previous: {
                 *                  previous: {...}
                 *              }
                 *              ...
                 *          },
                 *         at01hs: {...}
                 *         ...
                 *     },
                 * }
                 *
                 */
                let bots = node.sensorBots.concat(node.apiDataFetcherBots).concat(node.indicatorBots).concat(node.studyBots)

                bots.forEach(bot => {
                    let products = bot.products
                    products.forEach(product => {
                        let productName = UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(product.payload, 'singularVariableName')
                        if (product.record !== undefined) {
                            product.record.properties.forEach(property => {
                                let propertyName = UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(property.payload, 'codeName')
                                product.datasets.forEach(dataset => {
                                    let validTimeFrames = UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(dataset.payload, 'validTimeFrames')
                                    if (validTimeFrames !== undefined) {
                                        validTimeFrames.forEach(tf => {
                                            let timeFrame = 'at' + tf.replace('-', '')

                                            stringObjects.push(chartObjectPrefix + timeFrame + '.' + productName + '.' + propertyName)
                                            for (let i = 1; i <= numberOfPreviousSuffixes; i++) {
                                                stringObjects.push(chartObjectPrefix + timeFrame + getPreviousSuffixTimes(i) + productName + dot + propertyName)
                                            }

                                        })
                                    }
                                })
                            })
                        }
                    })
                })
                /**
                 * Getting all the Formula codes and create an object representation, all non-object children will be initialized with strings
                 *
                 * e.g : we will end with something like {
                 *     variable: {
                 *         last24hsDirection: "",
                 *         last24HsMax: ""
                 *     },
                 *     record: {
                 *         current: {
                 *             direction: ""
                 *         }
                 *     }
                 * }
                 * the above object will have as many properties as we can find in the entire workspace by scanning the formulas
                 *
                 */

                UI.projects.visualScripting.utilities.branches.nodeBranchToArray(node, 'Record Formula').forEach(node => {
                    /**
                     * Extract each code formula as an object to be merged with the next one until we end up with an object containing all the objects present in the formula with proper children
                     * The resulting object will be later used as model for autocompletion
                     */
                    objectMerge(recordFormulasObj, node.code.split('.').reduceRight((o, x) => ({[x]: o}), ""))

                })
            } else if (node.type === 'Trading Engine') {
                // Create an object representation for the engine
                tradingEngineObj = {tradingEngine: UI.projects.visualScripting.nodeActionFunctions.protocolNode.getProtocolNode(node, false, false, false, false, false, undefined)}
            }
        })

        // Enrich chart data with market and exchange structure
/*        UI.projects.workspaces.spaces.designSpace.workspace.workspaceNode.rootNodes.forEach(node => {
            if (node.type === 'Crypto Ecosystem') {
                node.cryptoExchanges.forEach(cxs => {
                    cxs.exchanges.forEach(exchange => {
                        let exchangeName = UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(exchange.payload, 'codeName')
                        exchange.exchangeMarkets.markets.forEach(market => {
                            let marketPair = UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(market.payload, 'codeName')
                            let baseAsset = marketPair.split('/')[0]
                            let quotedAsset = marketPair.split('/')[1]
                            stringObjects.forEach(chartObj => {
                                /!**
                                 * We will provide auto-complete only for assets pair found in Markets
                                 * Doing so we will avoid providing completion for assets that are not used in a market
                                 *!/

                                    //TODO: Disabled on purpose, causes high memory consumption when multiple exchanges are loaded
                                let market = marketPrefix + baseAsset + dot + quotedAsset + dot + chartObj
                                // stringObjects.push(market)
                                // stringObjects.push(exchangePrefix + exchangeName + dot + market)
                            })
                        })
                    })
                })
            }
        })*/

        //Actually building the objects for chart, market and exchange, no need for multiple objects, as one is enough for the autocomplete to work
        stringObjects.forEach(stringRepresentation => {
            objectMerge(chartMarketExchangeObj, stringRepresentation.split('.').reduceRight((o, x) => ({[x]: o}), ""))
        })


        function objectMerge(target, source) {
            for (const key of Object.keys(source)) {
                const currTarget = target[key];
                const currSource = source[key];

                if (currTarget) {
                    const objSource = typeof currSource === 'object';
                    const objTarget = typeof currTarget === 'object';

                    if (objSource && objTarget) {
                        void objectMerge(currTarget, currSource)
                        continue;
                    }
                }

                target[key] = currSource;
            }

            return target;
        }

        function getPreviousSuffixTimes(number) {
            let result = ''
            let previousString = 'previous.'
            let dotString = '.'
            for (let i = 0; i < number; i++) {
                if (i === 0) {
                    result += dotString
                }
                result += previousString
            }

            return result
        }

    }
The autocomplete models will be based on:
1.  Existing code in the data mines -> we will create models for each code node (it's like opening multiple files in vscode)
2.  Formulas from data mines by creating an object representation of all formulas see implementation below then passing it to the monaco registerCompletionItemProvider
2.  Trading engine loaded into the workspace - we create an obj. representation using getProtocolNode and we are using monaco registerCompletionItemProvider