Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Generate unique ID across view files in an application #719

Merged
merged 21 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
965c2f7
feat: support unique ID generation across a project
marufrasully Aug 2, 2024
6b0a6be
fix: validate all opened documents
marufrasully Aug 2, 2024
1c102b3
fix: validate all opened documents on file delete or rename
marufrasully Aug 2, 2024
bf260af
fix: add and adapt tests
marufrasully Aug 7, 2024
ad25972
Merge remote-tracking branch 'origin/master' into feat/generate-id
marufrasully Aug 7, 2024
151616f
fix: add change set
marufrasully Aug 7, 2024
7d30ae9
fix: failing test and clean up
marufrasully Aug 7, 2024
f1735ea
fix: remove dependency
marufrasully Aug 7, 2024
6cda198
fix: remove nyc. jest has build in coverage
marufrasully Aug 8, 2024
fec1fe8
fix: remove nyc cofig.js
marufrasully Aug 8, 2024
bbd1637
Merge remote-tracking branch 'origin' into feat/generate-id
marufrasully Aug 12, 2024
0e4bdd4
Merge remote-tracking branch 'origin/master' into feat/generate-id
marufrasully Aug 13, 2024
8b78a60
refactor: cache control in context and avoid context manipulation
marufrasully Aug 16, 2024
d5dc4a4
fix: change set
marufrasully Aug 16, 2024
8b51020
Merge remote-tracking branch 'origin/master' into feat/generate-id
marufrasully Aug 16, 2024
a26da65
fix: escpe SonarCloud reporting
marufrasully Aug 16, 2024
504019e
fix: snoare cloud issues
marufrasully Aug 19, 2024
eb374cf
fix: review comments and small improvment
marufrasully Aug 21, 2024
232dfcc
Merge remote-tracking branch 'origin/master' into feat/generate-id
marufrasully Aug 21, 2024
3f472d5
fix: performance optimization
marufrasully Aug 21, 2024
e21e313
chore: inclusive language
marufrasully Aug 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/spicy-trainers-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@ui5-language-assistant/vscode-ui5-language-assistant-bas-ext": patch
"vscode-ui5-language-assistant": patch
"@ui5-language-assistant/xml-views-completion": patch
"@ui5-language-assistant/xml-views-definition": patch
"@ui5-language-assistant/xml-views-validation": patch
"@ui5-language-assistant/xml-views-quick-fix": patch
"@ui5-language-assistant/xml-views-tooltip": patch
"@ui5-language-assistant/user-facing-text": patch
"@ui5-language-assistant/context": patch
---

feat: support unique id generation across view files in an application
10 changes: 0 additions & 10 deletions nyc.config.js

This file was deleted.

4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"build:quick": "lerna run compile && lerna run bundle && lerna run package",
"release:version": "lerna version --force-publish",
"release:publish": "lerna publish from-package --yes",
"ci": "npm-run-all format:validate ci:subpackages coverage:merge legal:*",
"ci": "npm-run-all format:validate ci:subpackages legal:*",
"compile": "yarn run clean && tsc --build",
"compile:watch": "yarn run clean && tsc --build --watch",
"format:fix": "prettier --write \"**/*.@(js|ts|json|md)\" --ignore-path=.gitignore",
Expand All @@ -26,7 +26,6 @@
"ci:subpackages": "lerna run ci",
"test": "lerna run test",
"coverage": "lerna run coverage",
"coverage:merge": "node ./scripts/merge-coverage",
"clean": "lerna run clean",
"update-snapshots": "lerna run update-snapshots",
"legal:delete": "lerna exec \"shx rm -rf .reuse LICENSES\" || true",
Expand Down Expand Up @@ -80,7 +79,6 @@
"make-dir": "3.1.0",
"mock-fs": "^5.2.0",
"npm-run-all": "4.1.5",
"nyc": "15.1.0",
"prettier": "2.8.7",
"rimraf": "3.0.2",
"shx": "0.3.3",
Expand Down
4 changes: 3 additions & 1 deletion packages/context/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
"lodash": "4.17.21",
"semver": "7.3.7",
"vscode-languageserver": "8.0.2",
"vscode-uri": "2.1.2"
"vscode-uri": "2.1.2",
"@xml-tools/ast": "5.0.0",
"@xml-tools/parser": "1.0.7"
},
"devDependencies": {
"@sap-ux/vocabularies-types": "0.10.14",
Expand Down
15 changes: 14 additions & 1 deletion packages/context/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { getServices } from "./services";
import { Context } from "./types";
import { getSemanticModel } from "./ui5-model";
import { getYamlDetails } from "./ui5-yaml";
import { getViewFiles } from "./utils/view-files";
import { join } from "path";

export {
initializeManifestData,
Expand Down Expand Up @@ -56,7 +58,18 @@ export async function getContext(
);
const services = await getServices(documentPath);
const customViewId = await getCustomViewId(documentPath);
return { manifestDetails, yamlDetails, ui5Model, services, customViewId };
const viewFiles = await getViewFiles(
join(manifestDetails.manifestPath, "..")
);
return {
manifestDetails,
yamlDetails,
ui5Model,
services,
customViewId,
viewFiles,
documentPath,
};
} catch (error) {
return error as Error;
}
Expand Down
16 changes: 14 additions & 2 deletions packages/context/src/cache.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Manifest } from "@sap-ux/project-access";
import type { UI5SemanticModel } from "@ui5-language-assistant/semantic-model-types";

import type { App, Project, YamlDetails } from "./types";
import type { XMLDocument } from "@xml-tools/ast";
import type { App, DocPath, Project, WebApp, YamlDetails } from "./types";

type AbsoluteAppRoot = string;
type AbsoluteProjectRoot = string;
Expand All @@ -13,13 +13,15 @@ class Cache {
private CAPServices: Map<AbsoluteProjectRoot, Map<string, string>>;
private ui5YamlDetails: Map<string, YamlDetails>;
private ui5Model: Map<string, UI5SemanticModel>;
private viewFiles: Record<string, Record<string, XMLDocument>>;
constructor() {
this.project = new Map();
this.manifest = new Map();
this.app = new Map();
this.CAPServices = new Map();
this.ui5YamlDetails = new Map();
this.ui5Model = new Map();
this.viewFiles = {};
}
reset() {
this.project = new Map();
Expand All @@ -28,6 +30,7 @@ class Cache {
this.CAPServices = new Map();
this.ui5YamlDetails = new Map();
this.ui5Model = new Map();
this.viewFiles = {};
}
/**
* Get entries of cached project
Expand Down Expand Up @@ -124,6 +127,15 @@ class Cache {
deleteUI5Model(key: string): boolean {
return this.ui5Model.delete(key);
}
/**
* Get entries of view files
*/
getViewFiles(webapp: WebApp): Record<DocPath, XMLDocument> {
return this.viewFiles[webapp] ?? {};
}
setViewFiles(webapp: WebApp, viewFiles: Record<DocPath, XMLDocument>): void {
this.viewFiles[webapp] = viewFiles;
}
}

/**
Expand Down
6 changes: 6 additions & 0 deletions packages/context/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
import { ConvertedMetadata } from "@sap-ux/vocabularies-types";
import type { Manifest } from "@sap-ux/project-access";
import { FetchResponse } from "@ui5-language-assistant/logic-utils";
import type { XMLDocument } from "@xml-tools/ast";

export const DEFAULT_UI5_FRAMEWORK = "SAPUI5";
export const DEFAULT_UI5_VERSION = "1.71.69";
Expand All @@ -24,12 +25,17 @@ export enum DirName {
Ext = "ext",
}

export type WebApp = string;
export type DocPath = string;

export interface Context {
ui5Model: UI5SemanticModel;
manifestDetails: ManifestDetails;
yamlDetails: YamlDetails;
services: Record<string, ServiceDetails>;
customViewId: string;
viewFiles: Record<DocPath, XMLDocument>;
documentPath: string;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/context/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export {
getLocalMetadataForService,
getProjectInfo,
getProjectRoot,
getWebappPath,
} from "./project";

export { getLogger } from "./logger";

export { getViewFiles } from "./view-files";
16 changes: 16 additions & 0 deletions packages/context/src/utils/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { join } from "path";
import findUp from "find-up";
import {
CAP_PROJECT_TYPE,
DirName,
ProjectKind,
ProjectType,
UI5_PROJECT_TYPE,
Expand Down Expand Up @@ -175,3 +176,18 @@ export async function getLocalMetadataForService(
}
return undefined;
}

/**
* Returns the path of the corresponding webapp folder for a given file
*
* The webapp folder contains the manifest.json file
*
* @param docPath document path of a file in current project
* @returns webapp path
*/
export const getWebappPath = function (docPath: string): string {
const pathSegments = docPath.split(DirName.Webapp);
pathSegments.pop();
const webappPath = join(...pathSegments, DirName.Webapp);
return webappPath;
};
57 changes: 57 additions & 0 deletions packages/context/src/utils/view-files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { readdir, readFile } from "fs/promises";
import { statSync } from "fs";
import { join } from "path";
import { isXMLView } from "@ui5-language-assistant/logic-utils";
import { parse, DocumentCstNode } from "@xml-tools/parser";
import { buildAst, XMLDocument } from "@xml-tools/ast";
import { cache } from "../cache";
import type { DocPath } from "../types";

/**
* Get `.view.xml` or `.fragment.xml` files under webapp folder.
*
* @param base base path to a folder or a file
* @param files xml files with its XMLDocument
* @returns xml files with its XMLDocument
*/
async function processViewFiles(
base: string,
files: Record<string, XMLDocument> = {}
): Promise<Record<DocPath, XMLDocument>> {
return new Promise((resolve) => {
return readdir(base).then(async (fileOrFolder) => {
for (const item of fileOrFolder) {
const itemPath = join(base, item);
if (statSync(itemPath).isDirectory()) {
await processViewFiles(itemPath, files);
} else {
if (isXMLView(itemPath)) {
const content = await readFile(itemPath, "utf-8");
const { cst, tokenVector } = parse(content);
const ast = buildAst(cst as DocumentCstNode, tokenVector);
files[itemPath] = ast;
}
}
}
return resolve(files);
});
});
}

/**
* Get `.view.xml` or `.fragment.xml` files under webapp folder.
*
* @param webappPath web app path
* @returns xml files with its XMLDocument
* @description it caches XMLDocument
*/
export async function getViewFiles(
webappPath: string
): Promise<Record<DocPath, XMLDocument>> {
if (Object.keys(cache.getViewFiles(webappPath)).length > 0) {
return cache.getViewFiles(webappPath);
}
const files = await processViewFiles(webappPath);
cache.setViewFiles(webappPath, files);
return files;
}
13 changes: 13 additions & 0 deletions packages/context/src/watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
getProjectRoot,
getProjectInfo,
getLogger,
getWebappPath,
} from "./utils";
import {
findManifestPath,
Expand All @@ -19,6 +20,7 @@ import { getYamlDetails } from "./ui5-yaml";
import { join } from "path";
import { FileName } from "@sap-ux/project-access";
import { CAP_PROJECT_TYPE, UI5_PROJECT_TYPE } from "./types";
import { isXMLView } from "@ui5-language-assistant/logic-utils";

/**
* React on manifest.json file change
Expand Down Expand Up @@ -224,7 +226,18 @@ export const reactOnXmlFileChange = async (
xmlUri: uri,
changeType,
});

const documentPath = URI.parse(uri).fsPath;
if (isXMLView(documentPath)) {
if (
changeType === FileChangeType.Created ||
changeType === FileChangeType.Deleted
) {
// reset cached view files
cache.setViewFiles(getWebappPath(documentPath), {});
}
}

const manifestPath = await findManifestPath(documentPath);
if (!manifestPath) {
return;
Expand Down
7 changes: 7 additions & 0 deletions packages/context/test/unit/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as manifest from "../../src/manifest";
import * as ui5Yaml from "../../src/ui5-yaml";
import * as ui5Model from "../../src/ui5-model";
import * as services from "../../src/services";
import * as viewFiles from "../../src/utils/view-files";
import { UI5SemanticModel } from "@ui5-language-assistant/semantic-model-types";
import { getContext, isContext } from "../../src/api";
import type { Context } from "../../src/types";
Expand Down Expand Up @@ -48,6 +49,9 @@ describe("context", () => {
const getServicesStub = jest
.spyOn(services, "getServices")
.mockResolvedValue({});
const getViewFilesStub = jest
.spyOn(viewFiles, "getViewFiles")
.mockResolvedValue({});
// act
const result = await getContext("path/to/xml/file");
// assert
Expand All @@ -58,12 +62,15 @@ describe("context", () => {
expect(getYamlDetailsStub).toHaveBeenCalled();
expect(getSemanticModelStub).toHaveBeenCalled();
expect(getServicesStub).toHaveBeenCalled();
expect(getViewFilesStub).toHaveBeenCalled();
expect(result).toContainAllKeys([
"services",
"manifestDetails",
"yamlDetails",
"customViewId",
"ui5Model",
"viewFiles",
"documentPath",
]);
});
it("throw connection error", async () => {
Expand Down
6 changes: 6 additions & 0 deletions packages/context/test/unit/cache.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { App, Project } from "../../src/types";
import { cache } from "../../src/cache";
import { UI5SemanticModel } from "@ui5-language-assistant/semantic-model-types";
import type { XMLDocument } from "@xml-tools/ast";

describe("cache", () => {
it("show singleton instance", async () => {
Expand Down Expand Up @@ -30,5 +31,10 @@ describe("cache", () => {
expect(result).toBeTrue();
expect(cache.getUI5ModelEntries()).toBeEmpty();
});

it("view files", () => {
cache.setViewFiles("webapp", { file: {} as XMLDocument });
expect(cache.getViewFiles("webapp")).toEqual({ file: {} });
});
});
});
25 changes: 25 additions & 0 deletions packages/context/test/unit/utils/project.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getProjectInfo,
getProjectRoot,
unifyServicePath,
getWebappPath,
} from "../../../src/utils/project";
import {
Config,
Expand Down Expand Up @@ -210,4 +211,28 @@ describe("project", () => {
expect(result).toEqual("/processor/one/two/");
});
});
describe("getWebappPath", () => {
it("webapp exists in file uri", () => {
// arrange
const uri = join(
"root",
"project",
"webapp",
"ext",
"my-test-file.view.xml"
);
// act
const result = getWebappPath(uri);
// assert
expect(join("root", "project", "webapp")).toStrictEqual(result);
});
it("webapp does not exist in file uri", () => {
// arrange
const uri = join("root", "project", "ext", "my-test-file.view.xml");
// act
const result = getWebappPath(uri);
// assert
expect("webapp").toStrictEqual(result);
});
});
});
Loading
Loading