@likec4/language-server 1.46.2 → 1.46.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Rpc.js +64 -62
- package/dist/bundled.mjs +2963 -2952
- package/dist/model-change/ModelChanges.js +69 -72
- package/dist/workspace/IndexManager.js +2 -8
- package/dist/workspace/LangiumDocuments.d.ts +8 -2
- package/dist/workspace/LangiumDocuments.js +20 -23
- package/dist/workspace/ProjectsManager.d.ts +12 -7
- package/dist/workspace/ProjectsManager.js +89 -73
- package/dist/workspace/WorkspaceManager.d.ts +1 -1
- package/dist/workspace/WorkspaceManager.js +2 -6
- package/package.json +12 -12
|
@@ -15,85 +15,86 @@ export class LikeC4ModelChanges {
|
|
|
15
15
|
}
|
|
16
16
|
async applyChange(changeView) {
|
|
17
17
|
const lspConnection = this.services.shared.lsp.Connection;
|
|
18
|
-
let result = null;
|
|
19
18
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
let { viewId, projectId: _projectId, change } = changeView;
|
|
20
|
+
const project = this.services.shared.workspace.ProjectsManager.ensureProject(_projectId);
|
|
21
|
+
logger.debug `Applying model change ${change.op} to view ${viewId} in project ${project.id}`;
|
|
22
|
+
const lookup = this.locator.locateViewAst(viewId, project.id);
|
|
23
|
+
if (!lookup) {
|
|
24
|
+
throw new Error(`View ${viewId} not found in project ${project.id}`);
|
|
25
|
+
}
|
|
26
|
+
const textDocument = {
|
|
27
|
+
uri: lookup.doc.textDocument.uri,
|
|
28
|
+
version: lookup.doc.textDocument.version,
|
|
29
|
+
};
|
|
30
|
+
// TODO refactor to use separate methods for save/reset operations
|
|
31
|
+
if (change.op === 'save-view-snapshot') {
|
|
32
|
+
invariant(viewId === change.layout.id, 'View ID does not match, expected ' + viewId + ', got ' + change.layout.id);
|
|
33
|
+
// If there is an existing manual layout v1
|
|
34
|
+
if (lookup.view.manualLayout) {
|
|
35
|
+
// We clean it up
|
|
36
|
+
await removeManualLayoutV1(this.services, { lookup }).catch(err => {
|
|
37
|
+
logger.warn(`Failed to remove manual layout v1 for view ${viewId} in project ${project.id}`, { err });
|
|
38
|
+
});
|
|
27
39
|
}
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
const location = await this.services.likec4.ManualLayouts.write(project, change.layout);
|
|
41
|
+
return {
|
|
42
|
+
success: true,
|
|
43
|
+
location,
|
|
31
44
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
const location = await this.services.likec4.ManualLayouts.write(project, change.layout);
|
|
43
|
-
result = {
|
|
44
|
-
success: true,
|
|
45
|
-
location,
|
|
46
|
-
};
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
if (change.op === 'reset-manual-layout') {
|
|
50
|
-
// If there is an existing manual layout v1
|
|
51
|
-
if (lookup.view.manualLayout) {
|
|
52
|
-
// We clean it up
|
|
53
|
-
await removeManualLayoutV1(this.services, { lookup }).catch(err => {
|
|
54
|
-
logger.warn(`Failed to remove manual layout v1 for view ${viewId} in project ${project.id}`, { err });
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
const location = await this.services.likec4.ManualLayouts.remove(project, viewId);
|
|
58
|
-
result = {
|
|
59
|
-
success: true,
|
|
60
|
-
location,
|
|
61
|
-
};
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
invariant(lspConnection, 'This change only supported in IDE (running as Extension)');
|
|
65
|
-
const { edits, modifiedRange } = this.convertToTextEdit({
|
|
66
|
-
lookup,
|
|
67
|
-
change,
|
|
68
|
-
});
|
|
69
|
-
if (!edits.length) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const applyResult = await lspConnection.workspace.applyEdit({
|
|
73
|
-
label: `LikeC4 - change view ${changeView.viewId}`,
|
|
74
|
-
edit: {
|
|
75
|
-
changes: {
|
|
76
|
-
[textDocument.uri]: edits,
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
if (!applyResult.applied) {
|
|
81
|
-
lspConnection.window.showErrorMessage(`Failed to apply changes ${applyResult.failureReason}`);
|
|
82
|
-
return;
|
|
45
|
+
}
|
|
46
|
+
if (change.op === 'reset-manual-layout') {
|
|
47
|
+
// If there is an existing manual layout v1
|
|
48
|
+
if (lookup.view.manualLayout) {
|
|
49
|
+
// We clean it up
|
|
50
|
+
await removeManualLayoutV1(this.services, { lookup }).catch(err => {
|
|
51
|
+
logger.warn(`Failed to remove manual layout v1 for view ${viewId} in project ${project.id}`, { err });
|
|
52
|
+
});
|
|
83
53
|
}
|
|
84
|
-
|
|
54
|
+
const location = await this.services.likec4.ManualLayouts.remove(project, viewId);
|
|
55
|
+
return {
|
|
85
56
|
success: true,
|
|
86
|
-
location
|
|
87
|
-
uri: textDocument.uri,
|
|
88
|
-
range: modifiedRange,
|
|
89
|
-
},
|
|
57
|
+
location,
|
|
90
58
|
};
|
|
59
|
+
}
|
|
60
|
+
invariant(lspConnection, 'This change only supported in IDE (running as Extension)');
|
|
61
|
+
const { edits, modifiedRange } = this.convertToTextEdit({
|
|
62
|
+
lookup,
|
|
63
|
+
change,
|
|
91
64
|
});
|
|
65
|
+
if (!edits.length) {
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: 'No changes to apply',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const applyResult = await lspConnection.workspace.applyEdit({
|
|
72
|
+
label: `LikeC4 - change view ${changeView.viewId}`,
|
|
73
|
+
edit: {
|
|
74
|
+
changes: {
|
|
75
|
+
[textDocument.uri]: edits,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
if (!applyResult.applied) {
|
|
80
|
+
lspConnection.window.showErrorMessage(`Failed to apply changes ${applyResult.failureReason}`);
|
|
81
|
+
return {
|
|
82
|
+
success: false,
|
|
83
|
+
error: `Failed to apply changes ${applyResult.failureReason}`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
success: true,
|
|
88
|
+
location: {
|
|
89
|
+
uri: textDocument.uri,
|
|
90
|
+
range: modifiedRange,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
92
93
|
}
|
|
93
94
|
catch (err) {
|
|
94
95
|
const error = loggable(wrapError(err, `Failed to apply change ${changeView.change.op} ${changeView.viewId}`));
|
|
95
96
|
logger.error(error);
|
|
96
|
-
|
|
97
|
+
return {
|
|
97
98
|
success: false,
|
|
98
99
|
error,
|
|
99
100
|
};
|
|
@@ -101,10 +102,6 @@ export class LikeC4ModelChanges {
|
|
|
101
102
|
finally {
|
|
102
103
|
this.services.likec4.ModelBuilder.clearCache();
|
|
103
104
|
}
|
|
104
|
-
return result ?? {
|
|
105
|
-
success: false,
|
|
106
|
-
error: 'Unknown error applying model change',
|
|
107
|
-
};
|
|
108
105
|
}
|
|
109
106
|
convertToTextEdit({ lookup, change }) {
|
|
110
107
|
switch (change.op) {
|
|
@@ -13,17 +13,11 @@ export class IndexManager extends DefaultIndexManager {
|
|
|
13
13
|
}
|
|
14
14
|
projectElements(projectId, nodeType, uris) {
|
|
15
15
|
const projects = this.services.workspace.ProjectsManager;
|
|
16
|
-
const project = projects.getProject(projectId);
|
|
17
|
-
const includePathStrings = project.includePaths?.map(uri => {
|
|
18
|
-
const path = uri.toString();
|
|
19
|
-
return path.endsWith('/') ? path : path + '/';
|
|
20
|
-
}) ?? [];
|
|
21
16
|
let documentUris = stream(this.symbolIndex.keys());
|
|
22
17
|
return documentUris
|
|
23
18
|
.filter(uri => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return (belongsToProject || inIncludePath) && (!uris || uris.has(uri));
|
|
19
|
+
return (!uris || uris.has(uri)) && (projects.belongsTo(uri) === projectId ||
|
|
20
|
+
projects.isIncluded(projectId, uri));
|
|
27
21
|
})
|
|
28
22
|
.flatMap(uri => this.getFileDescriptions(uri, nodeType));
|
|
29
23
|
}
|
|
@@ -5,15 +5,21 @@ import { type LikeC4LangiumDocument } from '../ast';
|
|
|
5
5
|
import type { LikeC4SharedServices } from '../module';
|
|
6
6
|
export declare class LangiumDocuments extends DefaultLangiumDocuments {
|
|
7
7
|
protected services: LikeC4SharedServices;
|
|
8
|
-
protected compare: (a: string | undefined, b: string | undefined) => number;
|
|
9
8
|
constructor(services: LikeC4SharedServices);
|
|
10
9
|
addDocument(document: LangiumDocument): void;
|
|
11
10
|
getDocument(uri: URI): LikeC4LangiumDocument | undefined;
|
|
12
11
|
get all(): Stream<LikeC4LangiumDocument>;
|
|
13
12
|
/**
|
|
14
|
-
* Returns all
|
|
13
|
+
* Returns all documents, excluding built-in documents and documents excluded by ProjectsManager.
|
|
15
14
|
*/
|
|
16
15
|
get allExcludingBuiltin(): Stream<LikeC4LangiumDocument>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns all documents for a project, including both project documents and documents included by the project.
|
|
18
|
+
*/
|
|
17
19
|
projectDocuments(projectId: ProjectId): Stream<LikeC4LangiumDocument>;
|
|
18
20
|
groupedByProject(): Record<ProjectId, NonEmptyArray<LikeC4LangiumDocument>>;
|
|
21
|
+
/**
|
|
22
|
+
* Reset the project IDs of all documents.
|
|
23
|
+
*/
|
|
24
|
+
resetProjectIds(): void;
|
|
19
25
|
}
|
|
@@ -14,7 +14,6 @@ const exclude = (doc) => {
|
|
|
14
14
|
};
|
|
15
15
|
export class LangiumDocuments extends DefaultLangiumDocuments {
|
|
16
16
|
services;
|
|
17
|
-
compare = compareNaturalHierarchically('/', true);
|
|
18
17
|
constructor(services) {
|
|
19
18
|
super(services);
|
|
20
19
|
this.services = services;
|
|
@@ -34,7 +33,7 @@ export class LangiumDocuments extends DefaultLangiumDocuments {
|
|
|
34
33
|
getDocument(uri) {
|
|
35
34
|
const doc = super.getDocument(uri);
|
|
36
35
|
if (doc && !exclude(doc)) {
|
|
37
|
-
doc.likec4ProjectId
|
|
36
|
+
doc.likec4ProjectId = this.services.workspace.ProjectsManager.belongsTo(doc);
|
|
38
37
|
}
|
|
39
38
|
if (doc && !isLikeC4LangiumDocument(doc)) {
|
|
40
39
|
throw new Error(`Document ${doc.uri.path} is not a LikeC4 document`);
|
|
@@ -46,7 +45,7 @@ export class LangiumDocuments extends DefaultLangiumDocuments {
|
|
|
46
45
|
.filter((doc) => {
|
|
47
46
|
if (doc.textDocument.languageId === LikeC4LanguageMetaData.languageId) {
|
|
48
47
|
if (!isLikeC4Builtin(doc.uri)) {
|
|
49
|
-
doc.likec4ProjectId
|
|
48
|
+
doc.likec4ProjectId = this.services.workspace.ProjectsManager.belongsTo(doc);
|
|
50
49
|
}
|
|
51
50
|
return true;
|
|
52
51
|
}
|
|
@@ -54,37 +53,35 @@ export class LangiumDocuments extends DefaultLangiumDocuments {
|
|
|
54
53
|
});
|
|
55
54
|
}
|
|
56
55
|
/**
|
|
57
|
-
* Returns all
|
|
56
|
+
* Returns all documents, excluding built-in documents and documents excluded by ProjectsManager.
|
|
58
57
|
*/
|
|
59
58
|
get allExcludingBuiltin() {
|
|
60
59
|
const projects = this.services.workspace.ProjectsManager;
|
|
61
|
-
return
|
|
62
|
-
|
|
63
|
-
return !exclude(doc) && !projects.isExcluded(doc);
|
|
60
|
+
return this.all.filter((doc) => {
|
|
61
|
+
return !(isLikeC4Builtin(doc.uri) || projects.isExcluded(doc));
|
|
64
62
|
});
|
|
65
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Returns all documents for a project, including both project documents and documents included by the project.
|
|
66
|
+
*/
|
|
66
67
|
projectDocuments(projectId) {
|
|
67
68
|
const projects = this.services.workspace.ProjectsManager;
|
|
68
|
-
const project = projects.getProject(projectId);
|
|
69
|
-
const projectFolder = project.folderUri.toString() + (project.folderUri.path.endsWith('/') ? '' : '/');
|
|
70
|
-
const includePathStrings = project.includePaths?.map(uri => {
|
|
71
|
-
const path = uri.toString();
|
|
72
|
-
return path.endsWith('/') ? path : path + '/';
|
|
73
|
-
}) ?? [];
|
|
74
69
|
return this.allExcludingBuiltin.filter(doc => {
|
|
75
|
-
|
|
76
|
-
// Always include documents from the project's own folder
|
|
77
|
-
if (docUri.startsWith(projectFolder)) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
// Check for addtional documents when the config has the `include:paths` property set.
|
|
81
|
-
if (includePathStrings.length > 0) {
|
|
82
|
-
return includePathStrings.some(includePath => docUri.startsWith(includePath));
|
|
83
|
-
}
|
|
84
|
-
return false;
|
|
70
|
+
return doc.likec4ProjectId === projectId || projects.isIncluded(projectId, doc.uri);
|
|
85
71
|
});
|
|
86
72
|
}
|
|
87
73
|
groupedByProject() {
|
|
88
74
|
return groupBy(this.allExcludingBuiltin.toArray(), prop('likec4ProjectId'));
|
|
89
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Reset the project IDs of all documents.
|
|
78
|
+
*/
|
|
79
|
+
resetProjectIds() {
|
|
80
|
+
super.all.forEach(doc => {
|
|
81
|
+
if (exclude(doc)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
delete doc.likec4ProjectId;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
90
87
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type IncludeConfig, type LikeC4ProjectConfig, type LikeC4ProjectConfigInput } from '@likec4/config';
|
|
2
|
-
import type { NonEmptyReadonlyArray } from '@likec4/core';
|
|
2
|
+
import type { NonEmptyArray, NonEmptyReadonlyArray } from '@likec4/core';
|
|
3
3
|
import type { ProjectId, scalar } from '@likec4/core/types';
|
|
4
4
|
import { type Cancellation, type LangiumDocument, URI, WorkspaceCache } from 'langium';
|
|
5
5
|
import type { Tagged } from 'type-fest';
|
|
@@ -20,7 +20,7 @@ interface ProjectData {
|
|
|
20
20
|
* Resolved include paths with both URI and folder string representations.
|
|
21
21
|
* These are additional directories that are part of this project.
|
|
22
22
|
*/
|
|
23
|
-
includePaths?:
|
|
23
|
+
includePaths?: NonEmptyArray<{
|
|
24
24
|
uri: URI;
|
|
25
25
|
folder: ProjectFolder;
|
|
26
26
|
}>;
|
|
@@ -36,7 +36,7 @@ export interface Project {
|
|
|
36
36
|
/**
|
|
37
37
|
* Resolved include paths as URIs (if configured).
|
|
38
38
|
*/
|
|
39
|
-
includePaths?: URI
|
|
39
|
+
includePaths?: NonEmptyReadonlyArray<URI>;
|
|
40
40
|
}
|
|
41
41
|
export declare class ProjectsManager {
|
|
42
42
|
#private;
|
|
@@ -74,6 +74,11 @@ export declare class ProjectsManager {
|
|
|
74
74
|
* Checks if the specified document should be excluded from processing.
|
|
75
75
|
*/
|
|
76
76
|
isExcluded(document: LangiumDocument | URI | string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Checks if the specified document is included by the project.
|
|
79
|
+
*/
|
|
80
|
+
isIncluded(projectId: ProjectId, document: LangiumDocument | URI | string): boolean;
|
|
81
|
+
includedInProjects(document: LangiumDocument | URI | string): ProjectId[];
|
|
77
82
|
/**
|
|
78
83
|
* Checks if it is a config file and it is not excluded by default exclude pattern
|
|
79
84
|
*
|
|
@@ -83,7 +88,7 @@ export declare class ProjectsManager {
|
|
|
83
88
|
/**
|
|
84
89
|
* Registers likec4 project by config file.
|
|
85
90
|
*/
|
|
86
|
-
registerConfigFile(configFile: URI): Promise<ProjectData>;
|
|
91
|
+
registerConfigFile(configFile: URI, cancelToken?: Cancellation.CancellationToken): Promise<ProjectData>;
|
|
87
92
|
/**
|
|
88
93
|
* Registers (or reloads) likec4 project by config file or config object.
|
|
89
94
|
* If there is some project registered at same folder, it will be reloaded.
|
|
@@ -91,14 +96,14 @@ export declare class ProjectsManager {
|
|
|
91
96
|
registerProject(opts: {
|
|
92
97
|
config: LikeC4ProjectConfig | LikeC4ProjectConfigInput;
|
|
93
98
|
folderUri: URI | string;
|
|
94
|
-
}): Promise<ProjectData>;
|
|
99
|
+
}, cancelToken?: Cancellation.CancellationToken): Promise<ProjectData>;
|
|
95
100
|
/**
|
|
96
101
|
* Determines which project the given document belongs to.
|
|
97
102
|
* If the document does not belong to any project, returns the default project ID.
|
|
98
103
|
*/
|
|
99
104
|
belongsTo(document: LangiumDocument | URI | string): scalar.ProjectId;
|
|
100
|
-
reloadProjects(): Promise<void>;
|
|
101
|
-
protected _reloadProjects(): Promise<void>;
|
|
105
|
+
reloadProjects(cancelToken?: Cancellation.CancellationToken): Promise<void>;
|
|
106
|
+
protected _reloadProjects(cancelToken?: Cancellation.CancellationToken): Promise<void>;
|
|
102
107
|
protected uniqueProjectId(name: string): scalar.ProjectId;
|
|
103
108
|
protected reset(): void;
|
|
104
109
|
rebuidProject(projectId: ProjectId, cancelToken?: Cancellation.CancellationToken): Promise<void>;
|