diff --git a/scripts/metadataProvider/MetadataProvider.ts b/scripts/metadataProvider/MetadataProvider.ts index 4db96ac3..03d07827 100644 --- a/scripts/metadataProvider/MetadataProvider.ts +++ b/scripts/metadataProvider/MetadataProvider.ts @@ -5,11 +5,16 @@ import { } from "@ui5-language-assistant/semantic-model"; import { BaseUI5Node, - UI5Aggregation, UI5Class, + UI5Namespace, + UI5Typedef, + UI5Interface, UI5SemanticModel, } from "@ui5-language-assistant/semantic-model-types"; +type SymbolOption = "aggregation" | "association" | "defaultAggregation" | "event" | "property"; +type SymbolOptionValues = Record; + export default class MetadataProvider { #model: UI5SemanticModel | null = null; async init(apiJsonsRoot: string, sapui5Version: string) { @@ -47,25 +52,67 @@ export default class MetadataProvider { return classMetadata.defaultAggregation?.name; } - // TODO: Add collection logic for associations, events, methods, properties (also inherited ones) - // + Use only one loop for all collections to save performance - getAggregationsForSymbol(symbol: BaseUI5Node): UI5Aggregation[] | undefined { - if (symbol.kind !== "UI5Class") { - return undefined; - } - let classMetadata = symbol as UI5Class; - // Collect own aggregations: - const ownAndBorrowedAggregations: UI5Aggregation[] = []; - ownAndBorrowedAggregations.push(...classMetadata.aggregations); + /** + * Collects all option values (aggregation, association, defaultAggregation, event, method, property) + * for a given symbol (incl. borrowed ones). + * @param {BaseUI5Node} symbol + * @returns {SymbolOptionValues} + */ + collectOptionValuesForSymbol(symbol: BaseUI5Node): SymbolOptionValues | undefined { + const symbolOptionValues: SymbolOptionValues = {}; + let symbolMetadata; - // Go up the inheritance chain and collect aggregations from all parent objects: - while (classMetadata.extends) { - classMetadata = classMetadata.extends; - if (classMetadata.aggregations) { - ownAndBorrowedAggregations.push(...classMetadata.aggregations); - } + switch (symbol.kind) { + case "UI5Class": + symbolMetadata = symbol as UI5Class; + // Collect own and borrowed option values: + while (symbolMetadata.extends) { + symbolMetadata.aggregations.forEach((aggregation) => { + symbolOptionValues[aggregation.name] = "aggregation"; + }); + symbolMetadata.associations.forEach((association) => { + symbolOptionValues[association.name] = "association"; + }); + if (symbolMetadata.defaultAggregation) { + symbolOptionValues[symbolMetadata.defaultAggregation.name] = "defaultAggregation"; + } + symbolMetadata.events.forEach((event) => { + symbolOptionValues[event.name] = "event"; + }); + symbolMetadata.properties.forEach((property) => { + symbolOptionValues[property.name] = "property"; + }); + symbolMetadata = symbolMetadata.extends; + } + break; + /* case "UI5Enum": // Disabled because UI5Enum does not contain any option values + symbolMetadata = symbol as UI5Enum; + break; + case "UI5Function": // Disabled because UI5Function does not contain any option values + symbolMetadata = symbol as UI5Function; + break; */ + case "UI5Namespace": + symbolMetadata = symbol as UI5Namespace; + symbolMetadata.events.forEach((event) => { + symbolOptionValues[event.name] = "event"; + }); + break; + case "UI5Typedef": + symbolMetadata = symbol as UI5Typedef; + // NPM package "@ui5-language-assistant/semantic-model-types" was not updated: + // symbolMetadata.properties.forEach((property) => { + // symbolOptionValues[property.name] = "property"; + // }); + break; + case "UI5Interface": + symbolMetadata = symbol as UI5Interface; + symbolMetadata.events.forEach((event) => { + symbolOptionValues[event.name] = "event"; + }); + break; + default: + return undefined; } - - return ownAndBorrowedAggregations; + return symbolOptionValues; } } diff --git a/scripts/metadataProvider/createMetadataInfo.ts b/scripts/metadataProvider/createMetadataInfo.ts index 131c4859..26371708 100644 --- a/scripts/metadataProvider/createMetadataInfo.ts +++ b/scripts/metadataProvider/createMetadataInfo.ts @@ -56,23 +56,17 @@ export default async function createMetadataInfo(apiJsonsRoot: string, sapui5Ver forEachSymbol(semanticModel, (symbol, symbolName) => { apiExtract.metadata[symbolName] = {}; - // TODO: Add metadata generation for associations, events, methods, properties - - // Aggregations: - const aggregations = metadataProvider.getAggregationsForSymbol(symbol); - if (aggregations) { - aggregations.forEach((aggregation) => { - apiExtract.metadata[symbolName][aggregation.name] = "aggregation"; - }); - } - - // Default aggregation: - const defaultAggregation = metadataProvider.getDefaultAggregationForSymbol(symbol); - if (defaultAggregation) { - apiExtract.metadata[symbolName][defaultAggregation] = "defaultAggregation"; + // Generate metadata: + if (isAllowedSymbolKind(symbol.kind)) { + const symbolOptionValues = metadataProvider.collectOptionValuesForSymbol(symbol); + if (symbolOptionValues) { + Object.entries(symbolOptionValues).forEach(([optionName, optionValue]) => { + apiExtract.metadata[symbolName][optionName] = optionValue; + }); + } } - // Deprecation: + // deprecations: if (symbol.deprecatedInfo?.isDeprecated) { const deprecationText = getDeprecationText(symbol.deprecatedInfo) ?? "deprecated"; if (isAllowedSymbolKind(symbol.kind)) { diff --git a/src/utils/ApiExtract.ts b/src/utils/ApiExtract.ts index 74486d8a..16851954 100644 --- a/src/utils/ApiExtract.ts +++ b/src/utils/ApiExtract.ts @@ -1,15 +1,14 @@ import {readFile} from "node:fs/promises"; export type AllowedSymbolKind = "UI5Class" | "UI5Enum" | "UI5Interface" | "UI5Namespace" | "UI5Typedef" | "UI5Function"; -export type AllowedMetadataOptions = "aggregation" | "association" | "defaultAggregation" | "event" | - "method" | "property"; +export type AllowedSymbolOption = "aggregation" | "association" | "defaultAggregation" | "event" | "property"; export interface ApiExtractJson { framework: { name: string; version: string; }; - metadata: Record>; + metadata: Record>; deprecations: Record>; } @@ -31,9 +30,9 @@ class ApiExtractImpl implements ApiExtract { } getDefaultAggregation(className: string): string { - // TODO: Implement this method with some clever logic - // (Don't loop through entire metadata and check each symbol's default aggregation) - return className; + // return this.data.defaultAggregations[className]; + // TODO: Implement this method + return ""; } getDeprecationInfo(symbolName: string): DeprecationInfo | undefined {