Skip to content

Commit

Permalink
Merge pull request #506 from IBM/fix/tool-tips
Browse files Browse the repository at this point in the history
Add Code4i tooltips for libraries, objects, members, and ifs files
  • Loading branch information
edmundreinhardt authored Jul 5, 2024
2 parents 36ac5ef + 8565d21 commit 77cbf0e
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 56 deletions.
15 changes: 2 additions & 13 deletions l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@
"Object Libraries": "Object Libraries",
"Work with the set of libraries defined in the curlib, objlib, preUsrlibl, and postUsrlibl entries of the iproj.json": "Work with the set of libraries defined in the curlib, objlib, preUsrlibl, and postUsrlibl entries of the iproj.json",
"Please connect to an IBM i": "Please connect to an IBM i",
"Text: {0}\n": "Text: {0}\n",
"Attribute: {0}\n": "Attribute: {0}\n",
"Type: {0}": "Type: {0}",
"Migrating Source": "Migrating Source",
"Verifying makei is installed...": "Verifying makei is installed...",
"Required component ({0}) to migrate source not installed on host IBM i. Run {1} to get it.": "Required component ({0}) to migrate source not installed on host IBM i. Run {1} to get it.",
Expand Down Expand Up @@ -111,12 +108,6 @@
"{0} does not contain any source files": "{0} does not contain any source files",
"Workspace folder not specified": "Workspace folder not specified",
"No source files selected to be migrated": "No source files selected to be migrated",
"Extension: {0}\n": "Extension: {0}\n",
"ASP: {0}\n": "ASP: {0}\n",
"Record Length: {0}\n": "Record Length: {0}\n",
"Lines: {0}\n": "Lines: {0}\n",
"Created: {0}\n": "Created: {0}\n",
"Changed: {0}": "Changed: {0}",
"Reveal in Explorer": "Reveal in Explorer",
"Failed to retrieve project": "Failed to retrieve project",
"Enter build command ({0} resolves to the base file name being edited. {1} resolves to the full IFS path corresponding to the source in the editor. {2} resolves to the IBM i hostname. {3} resolves to the user profile that the command will be executed under. {4} resolves to the name of the current git branch if this project is managed by git.)": "Enter build command ({0} resolves to the base file name being edited. {1} resolves to the full IFS path corresponding to the source in the editor. {2} resolves to the IBM i hostname. {3} resolves to the user profile that the command will be executed under. {4} resolves to the name of the current git branch if this project is managed by git.)",
Expand Down Expand Up @@ -188,9 +179,8 @@
"Deleted {0}": "Deleted {0}",
"Error deleting member! {0}": "Error deleting member! {0}",
"Include Paths": "Include Paths",
"Size: {0}\n": "Size: {0}\n",
"Owner: {0}\n": "Owner: {0}\n",
"Modified: {0}": "Modified: {0}",
"Not specified": "Not specified",
"Not found": "Not found",
"Open Stream File": "Open Stream File",
"Add Folder to Workspace": "Add Folder to Workspace",
"Please configure project metadata": "Please configure project metadata",
Expand All @@ -204,7 +194,6 @@
"Please configure environment file": "Please configure environment file",
"Create .env": "Create .env",
"Unable to retrieve environment variables": "Unable to retrieve environment variables",
"Not specified": "Not specified",
"Delete Upon Deploy\n": "Delete Upon Deploy\n",
"License: {0}": "License: {0}",
"No job log found": "No job log found",
Expand Down
4 changes: 2 additions & 2 deletions src/views/projectExplorer/errorItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,12 @@ export default class ErrorItem extends TreeItem implements ProjectExplorerTreeIt
);
}

static createIncludePathNotSpecifiedError(workspaceFolder: WorkspaceFolder, includePath: string, position: Position | undefined): ErrorItem {
static createIncludePathError(workspaceFolder: WorkspaceFolder, includePath: string, position: Position | undefined, description: string): ErrorItem {
return new ErrorItem(
workspaceFolder,
includePath,
{
description: l10n.t('Not specified'),
description: description,
contextValue: ContextValue.includePath +
(position === 'first' ? ContextValue.first : '') +
(position === 'last' ? ContextValue.last : '') +
Expand Down
7 changes: 2 additions & 5 deletions src/views/projectExplorer/ifsDirectory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@ export default class IFSDirectory extends TreeItem implements ProjectExplorerTre

this.contextValue = IFSDirectory.contextValue;
this.iconPath = new ThemeIcon(`symbol-folder`);
this.tooltip = l10n.t('Name: {0}\n', ifsDirectoryInfo.name) +
l10n.t('Path: {0}\n', ifsDirectoryInfo.path) +
(ifsDirectoryInfo.size ? l10n.t('Size: {0}\n', ifsDirectoryInfo.size) : ``) +
(ifsDirectoryInfo.owner ? l10n.t('Owner: {0}\n', ifsDirectoryInfo.owner) : ``) +
(ifsDirectoryInfo.modified ? l10n.t('Modified: {0}', ifsDirectoryInfo.modified.toLocaleString()) : ``);
const ibmi = getInstance();
this.tooltip = ibmi?.getContent().ifsFileToToolTip(ifsDirectoryInfo.path, ifsDirectoryInfo);
this.description = (custom && custom.description ? custom.description : undefined);
}

Expand Down
8 changes: 3 additions & 5 deletions src/views/projectExplorer/ifsFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder, l1
import { ProjectExplorerTreeItem } from "./projectExplorerTreeItem";
import { ContextValue } from "../../ibmiProjectExplorer";
import * as vscodeIbmiTypes from "@halcyontech/vscode-ibmi-types";
import { getInstance } from "../../ibmi";

/**
* Tree item for an IFS file.
Expand All @@ -20,11 +21,8 @@ export default class IFSFile extends TreeItem implements ProjectExplorerTreeItem
this.ifsFileInfo = ifsFileInfo;
this.contextValue = IFSFile.contextValue;
this.iconPath = new ThemeIcon(`file`);
this.tooltip = l10n.t('Name: {0}\n', ifsFileInfo.name) +
l10n.t('Path: {0}\n', ifsFileInfo.path) +
(ifsFileInfo.size ? l10n.t('Size: {0}\n', ifsFileInfo.size) : ``) +
(ifsFileInfo.owner ? l10n.t('Owner: {0}\n', ifsFileInfo.owner) : ``) +
(ifsFileInfo.modified ? l10n.t('Modified: {0}', ifsFileInfo.modified.toLocaleString()) : ``);
const ibmi = getInstance();
this.tooltip = ibmi?.getContent().ifsFileToToolTip(ifsFileInfo.path, ifsFileInfo);
this.resourceUri = this.getIFSFileResourceUri();
this.command = {
command: `vscode.open`,
Expand Down
26 changes: 21 additions & 5 deletions src/views/projectExplorer/includePaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import RemoteIncludePath from "./remoteIncludePath";
import * as path from "path";
import ErrorItem from "./errorItem";
import { Position } from "../../iproject";
import { getInstance } from "../../ibmi";

/**
* Tree item for Include Paths heading.
Expand Down Expand Up @@ -46,7 +47,7 @@ export default class IncludePaths extends TreeItem implements ProjectExplorerTre
}

if (includePath.startsWith('&')) {
items.push(ErrorItem.createIncludePathNotSpecifiedError(this.workspaceFolder, includePath, position));
items.push(ErrorItem.createIncludePathError(this.workspaceFolder, includePath, position, l10n.t('Not specified')));
continue;
}

Expand All @@ -65,14 +66,29 @@ export default class IncludePaths extends TreeItem implements ProjectExplorerTre
// Relative local include path
items.push(new LocalIncludePath(this.workspaceFolder, includePath, includePathUri, position, variable));
} catch (e) {
const ibmi = getInstance();
const connection = ibmi!.getConnection();
const deployLocation = iProject!.getDeployLocation();

if (includePath.startsWith('/') || !deployLocation) {
// Absolute remote include path
items.push(new RemoteIncludePath(this.workspaceFolder, includePath, position, variable));
const directoryExists = (await connection?.sendCommand({ command: `test -d ${includePath}` }));

if (directoryExists && directoryExists.code === 0) {
// Absolute remote include path
items.push(new RemoteIncludePath(this.workspaceFolder, includePath, position, variable));
} else {
items.push(ErrorItem.createIncludePathError(this.workspaceFolder, includePath, position, l10n.t('Not found')));
}
} else {
// Relative remote include path
const absoluteIncludePath = path.posix.join(deployLocation, includePath);
items.push(new RemoteIncludePath(this.workspaceFolder, absoluteIncludePath, position, variable, { label: includePath }));
const directoryExists = (await connection?.sendCommand({ command: `test -d ${absoluteIncludePath}` }));

if (directoryExists && directoryExists.code === 0) {
// Relative remote include path
items.push(new RemoteIncludePath(this.workspaceFolder, absoluteIncludePath, position, variable, { label: includePath }));
} else {
items.push(ErrorItem.createIncludePathError(this.workspaceFolder, includePath, position, l10n.t('Not found')));
}
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/views/projectExplorer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { ConnectionData, DeploymentMethod, ObjectItem } from "@halcyontech/vscode-ibmi-types";
import { DeploymentPath } from "@halcyontech/vscode-ibmi-types/api/Storage";
import * as path from "path";
import { ConfigurationTarget, EventEmitter, ExtensionContext, ProgressLocation, QuickPickItem, TreeDataProvider, TreeView, Uri, WorkspaceFolder, commands, env, l10n, window, workspace } from "vscode";
import { CancellationToken, ConfigurationTarget, EventEmitter, ExtensionContext, ProgressLocation, QuickPickItem, TreeDataProvider, TreeItem, TreeView, Uri, WorkspaceFolder, commands, env, l10n, window, workspace } from "vscode";
import { EnvironmentManager } from "../../environmentManager";
import { IProjectT } from "../../iProjectT";
import { getDeployTools, getInstance, getTools } from "../../ibmi";
Expand Down Expand Up @@ -1289,7 +1289,6 @@ export default class ProjectExplorer implements TreeDataProvider<ProjectExplorer
);
}


setTreeView(treeView: TreeView<ProjectExplorerTreeItem>) {
this.treeView = treeView;
}
Expand Down Expand Up @@ -1363,6 +1362,14 @@ export default class ProjectExplorer implements TreeDataProvider<ProjectExplorer
}
}

async resolveTreeItem(item: TreeItem, element: ProjectExplorerTreeItem, token: CancellationToken): Promise<ProjectExplorerTreeItem> {
if (element.getToolTip) {
element.tooltip = await element.getToolTip();
}

return element;
}

/**
* Get the project tree item associated with an IBM i project.
*
Expand Down
9 changes: 3 additions & 6 deletions src/views/projectExplorer/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* (c) Copyright IBM Corp. 2023
*/

import { ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder, l10n, window } from "vscode";
import { MarkdownString, ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder, l10n, window } from "vscode";
import { ProjectExplorerTreeItem } from "./projectExplorerTreeItem";
import { getInstance } from "../../ibmi";
import ObjectFile from "./objectFile";
Expand Down Expand Up @@ -47,11 +47,8 @@ export default class Library extends TreeItem implements ProjectExplorerTreeItem
this.description = (variable ? `${variable} - ` : ``) +
(libraryInfo.text.trim() !== '' ? `${libraryInfo.text} ` : ``) +
(libraryInfo.attribute?.trim() !== '' ? `(${libraryInfo.attribute})` : ``);
this.tooltip = l10n.t('Name: {0}\n', libraryInfo.name) +
l10n.t('Path: {0}\n', this.path) +
(libraryInfo.text.trim() !== '' ? l10n.t('Text: {0}\n', libraryInfo.text) : ``) +
(libraryInfo.attribute ? l10n.t('Attribute: {0}\n', libraryInfo.attribute) : ``) +
l10n.t('Type: {0}', libraryInfo.type);
const ibmi = getInstance();
this.tooltip = ibmi?.getContent().objectToToolTip([libraryInfo.library, libraryInfo.name].join(`/`), libraryInfo);
let iconColor: ThemeColor | undefined;
switch (this.libraryType) {
case LibraryType.systemLibrary:
Expand Down
14 changes: 4 additions & 10 deletions src/views/projectExplorer/memberFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
* (c) Copyright IBM Corp. 2023
*/

import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder, l10n } from "vscode";
import { MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder, l10n } from "vscode";
import { IBMiMember } from "@halcyontech/vscode-ibmi-types";
import { ProjectExplorerTreeItem } from "./projectExplorerTreeItem";
import { ContextValue } from "../../ibmiProjectExplorer";
import { getInstance } from "../../ibmi";

/**
* Tree item for a member file.
Expand All @@ -23,16 +24,9 @@ export default class MemberFile extends TreeItem implements ProjectExplorerTreeI
this.contextValue = MemberFile.contextValue;
this.iconPath = new ThemeIcon(`file`);
this.description = memberFileInfo.text;
this.tooltip = l10n.t('Name: {0}\n', memberFileInfo.name) +
l10n.t('Path: {0}\n', this.path) +
(memberFileInfo.text && memberFileInfo.text.trim() !== '' ? l10n.t('Text: {0}\n', memberFileInfo.text) : ``) +
l10n.t('Extension: {0}\n', extension) +
(memberFileInfo.asp ? l10n.t('ASP: {0}\n', memberFileInfo.asp) : ``) +
(memberFileInfo.recordLength ? l10n.t('Record Length: {0}\n', memberFileInfo.recordLength) : ``) +
(memberFileInfo.lines ? l10n.t('Lines: {0}\n', memberFileInfo.lines) : ``) +
(memberFileInfo.created ? l10n.t('Created: {0}\n', memberFileInfo.created.toLocaleString()) : ``) +
(memberFileInfo.changed ? l10n.t('Changed: {0}', memberFileInfo.changed.toLocaleString()) : ``);
this.resourceUri = this.getMemberResourceUri();
const ibmi = getInstance();
this.tooltip = ibmi?.getContent().memberToToolTip([memberFileInfo.library, memberFileInfo.file, `${memberFileInfo.name}.${extension}`].join(`/`), memberFileInfo);
this.command = {
command: `vscode.open`,
title: `Open Member`,
Expand Down
17 changes: 11 additions & 6 deletions src/views/projectExplorer/objectFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* (c) Copyright IBM Corp. 2023
*/

import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder, l10n, window } from "vscode";
import { MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder, l10n, window } from "vscode";
import { ProjectExplorerTreeItem } from "./projectExplorerTreeItem";
import MemberFile from "./memberFile";
import { getInstance } from "../../ibmi";
Expand Down Expand Up @@ -31,11 +31,6 @@ export default class ObjectFile extends TreeItem implements ProjectExplorerTreeI
this.iconPath = new ThemeIcon(icon);
this.description = (objectFileInfo.text.trim() !== '' ? `${objectFileInfo.text} ` : ``) +
(objectFileInfo.attribute?.trim() !== '' ? `(${objectFileInfo.attribute})` : '');
this.tooltip = l10n.t('Name: {0}\n', objectFileInfo.name) +
l10n.t('Path: {0}\n', this.path) +
(objectFileInfo.text.trim() !== '' ? l10n.t('Text: {0}\n', objectFileInfo.text) : ``) +
(objectFileInfo.attribute ? l10n.t('Attribute: {0}\n', objectFileInfo.attribute) : ``) +
l10n.t('Type: {0}', objectFileInfo.type);
this.resourceUri = this.getObjectResourceUri();
}

Expand All @@ -57,6 +52,16 @@ export default class ObjectFile extends TreeItem implements ProjectExplorerTreeI
return items;
}

async getToolTip() {
const ibmi = getInstance();
const path = [this.objectFileInfo.library, this.objectFileInfo.name].join(`/`);
if (this.objectFileInfo.sourceFile) {
return await ibmi?.getContent().sourcePhysicalFileToToolTip(path, this.objectFileInfo);
} else {
return ibmi?.getContent().objectToToolTip(path, this.objectFileInfo);
}
}

getObjectResourceUri() {
const type = this.objectFileInfo.type.startsWith(`*`) ? this.objectFileInfo.type.substring(1) : this.objectFileInfo.type;
const path = `${this.objectFileInfo.library}/${this.objectFileInfo.name}.${type}`;
Expand Down
9 changes: 7 additions & 2 deletions src/views/projectExplorer/projectExplorerTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* (c) Copyright IBM Corp. 2023
*/

import { TreeItem, WorkspaceFolder } from "vscode";
import { MarkdownString, TreeItem, WorkspaceFolder } from "vscode";

/**
* Represents a tree item in the Project Explorer view.
Expand All @@ -19,5 +19,10 @@ export interface ProjectExplorerTreeItem extends TreeItem {
*
* @return Children of this tree item.
*/
getChildren(): ProjectExplorerTreeItem[] | Promise<ProjectExplorerTreeItem[]>;
getChildren: () => ProjectExplorerTreeItem[] | Promise<ProjectExplorerTreeItem[]>;

/**
* Get the markdown tooltip of this tree item.
*/
getToolTip?: () => Promise<MarkdownString | undefined>;
}

0 comments on commit 77cbf0e

Please sign in to comment.