refactor: Fix null check and implicit any (#389)

This commit is contained in:
Qinzhou Xu 2020-12-09 11:09:15 +08:00 коммит произвёл GitHub
Родитель 26a86e895a
Коммит 35820eb264
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
37 изменённых файлов: 195 добавлений и 179 удалений

Просмотреть файл

@ -28,7 +28,7 @@ export function getExpService() {
}
export function init(context: vscode.ExtensionContext): void {
const packageJson: {} = require("../package.json");
const packageJson: {[key: string]: any} = require("../package.json");
// tslint:disable: no-string-literal
const extensionName = `${packageJson["publisher"]}.${packageJson["name"]}`;
const extensionVersion = packageJson["version"];

Просмотреть файл

@ -2,7 +2,7 @@
// Licensed under the MIT license.
import { basename } from "path";
import { commands, DiagnosticSeverity, languages, Uri, window } from "vscode";
import { commands, DiagnosticSeverity, languages, QuickPickItem, Uri, window } from "vscode";
import { instrumentOperation, sendInfo, sendOperationError, setErrorCode } from "vscode-extension-telemetry-wrapper";
import { Commands, executeJavaExtensionCommand } from "./commands";
import { Jdtls } from "./java/jdtls";
@ -71,14 +71,14 @@ function checkErrorsReportedByJavaExtension(): boolean {
}
async function showFixSuggestions(operationId: string) {
let buildFiles = [];
let buildFiles: string[] = [];
try {
buildFiles = await Jdtls.resolveBuildFiles();
} catch (error) {
// do nothing
}
const pickitems = [];
const pickitems: QuickPickItem[] = [];
pickitems.push({
label: "Clean workspace cache",
detail: "Clean the stale workspace and reload the window",

Просмотреть файл

@ -92,11 +92,11 @@ export namespace Commands {
export const WORKBENCH_ACTION_FILES_OPENFILEFOLDER = "workbench.action.files.openFileFolder";
}
export function executeJavaLanguageServerCommand(...rest) {
export function executeJavaLanguageServerCommand(...rest: any[]) {
return executeJavaExtensionCommand(Commands.EXECUTE_WORKSPACE_COMMAND, ...rest);
}
export async function executeJavaExtensionCommand(commandName: string, ...rest) {
export async function executeJavaExtensionCommand(commandName: string, ...rest: any[]) {
// TODO: need to handle error and trace telemetry
return commands.executeCommand(commandName, ...rest);
}

Просмотреть файл

@ -21,7 +21,7 @@ export class LibraryController implements Disposable {
this.disposable = Disposable.from(
instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_ADD_LIBRARIES, () => this.addLibraries()),
instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_REMOVE_LIBRARY, (node: DataNode) =>
this.removeLibrary(Uri.parse(node.uri).fsPath)),
node.uri && this.removeLibrary(Uri.parse(node.uri).fsPath)),
instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_REFRESH_LIBRARIES, () =>
this.refreshLibraries()),
);

Просмотреть файл

@ -51,10 +51,10 @@ async function getPackageFsPath(node: DataNode): Promise<string> {
});
if (packageRoots.length < 1) {
// This might happen for an invisible project with "_" as its root
const packageNode: DataNode = childrenNodes.find((child) => {
const packageNode: DataNode | undefined = childrenNodes.find((child) => {
return child.nodeData.kind === NodeKind.Package;
});
if (packageNode) {
if (packageNode?.uri) {
return getPackageRootPath(Uri.parse(packageNode.uri).fsPath, packageNode.name);
}
return "";
@ -76,7 +76,7 @@ async function getPackageFsPath(node: DataNode): Promise<string> {
}
}
return Uri.parse(node.uri).fsPath;
return node.uri ? Uri.parse(node.uri).fsPath : "";
}
function getNewFilePath(basePath: string, className: string): string {
@ -87,6 +87,10 @@ function getNewFilePath(basePath: string, className: string): string {
}
export async function newPackage(node: DataNode): Promise<void> {
if (!node.uri) {
return;
}
let defaultValue: string;
let packageRootPath: string;
const nodeKind = node.nodeData.kind;

Просмотреть файл

@ -11,6 +11,9 @@ export function isMutable(node: DataNode): boolean {
const resourceOrTypeExp = /java:(file|type|folder)(?=.*?\b\+uri\b)/;
const contextValue = node.computeContextValue();
if (!contextValue) {
return false;
}
return packageExp.test(contextValue) || resourceOrTypeExp.test(contextValue);
}

Просмотреть файл

@ -94,7 +94,7 @@ export class ExportJarTaskProvider implements TaskProvider {
const stepMetadata: IStepMetadata = {
entry: undefined,
workspaceFolder: folder,
projectList: await Jdtls.getProjects(folder.uri.toString()),
projectList: await Jdtls.getProjects(folder.uri.toString()) || [],
steps: [],
elements: [],
classpaths: [],
@ -115,7 +115,7 @@ export class ExportJarTaskProvider implements TaskProvider {
}
this.tasks = [];
for (const folder of folders) {
const projectList: INodeData[] = await Jdtls.getProjects(folder.uri.toString());
const projectList: INodeData[] = await Jdtls.getProjects(folder.uri.toString()) || [];
const elementList: string[] = [];
if (_.isEmpty(projectList)) {
continue;
@ -128,7 +128,7 @@ export class ExportJarTaskProvider implements TaskProvider {
"${" + ExportJarConstants.DEPENDENCIES + ":" + project.name + "}");
}
}
const mainClasses: IMainClassInfo[] = await Jdtls.getMainClasses(folder.uri.toString());
const mainClasses: IMainClassInfo[] = await Jdtls.getMainClasses(folder.uri.toString()) || [];
const defaultDefinition: IExportJarTaskDefinition = {
type: ExportJarTaskProvider.exportJarType,
label: `${ExportJarTaskProvider.exportJarType}: exportjar:${folder.name}`,
@ -141,7 +141,7 @@ export class ExportJarTaskProvider implements TaskProvider {
const stepMetadata: IStepMetadata = {
entry: undefined,
workspaceFolder: folder,
projectList: await Jdtls.getProjects(folder.uri.toString()),
projectList: await Jdtls.getProjects(folder.uri.toString()) || [],
steps: [],
elements: [],
classpaths: [],
@ -188,7 +188,7 @@ class ExportJarTaskTerminal implements Pseudoterminal {
const artifactMap: Map<string, string[]> = new Map<string, string[]>();
const testOutputFolderMap: Map<string, string[]> = new Map<string, string[]>();
const testArtifactMap: Map<string, string[]> = new Map<string, string[]>();
const projectList: INodeData[] = await Jdtls.getProjects(this.stepMetadata.workspaceFolder.uri.toString());
const projectList: INodeData[] | undefined = await Jdtls.getProjects(this.stepMetadata.workspaceFolder.uri.toString()) || [];
for (const project of projectList) {
await this.setClasspathMap(project, "runtime", outputFolderMap, artifactMap);
await this.setClasspathMap(project, "test", testOutputFolderMap, testArtifactMap);
@ -333,7 +333,7 @@ class ExportJarTaskTerminal implements Pseudoterminal {
}
const sources: IClasspath[] = [];
for (const glob of await globby(globPatterns)) {
const tireNode: TrieNode<IUriData> | undefined = trie.find(
const tireNode: TrieNode<IUriData | undefined> | undefined = trie.find(
Uri.file(platform() === "win32" ? toWinPath(glob) : glob).fsPath, /* returnEarly = */true);
if (!tireNode?.value?.uri) {
continue;

Просмотреть файл

@ -77,12 +77,12 @@ export class GenerateJarExecutor implements IExportJarStepExecutor {
if (_.isEmpty(classpaths)) {
return reject(new Error(ExportJarMessages.CLASSPATHS_EMPTY));
}
const exportResult: IExportResult = await Jdtls.exportJar(basename(mainClass), classpaths, destPath);
if (exportResult.result === true) {
const exportResult: IExportResult | undefined = await Jdtls.exportJar(basename(mainClass), classpaths, destPath);
if (exportResult?.result === true) {
stepMetadata.outputPath = destPath;
return resolve(true);
} else {
return reject(new Error("Export jar failed." + exportResult.message));
return reject(new Error("Export jar failed." + exportResult?.message));
}
});
});

Просмотреть файл

@ -34,18 +34,18 @@ export class ResolveJavaProjectExecutor implements IExportJarStepExecutor {
stepMetadata.workspaceFolder = folder;
}
}
stepMetadata.projectList = await Jdtls.getProjects(workspaceUri.toString());
stepMetadata.projectList = await Jdtls.getProjects(workspaceUri.toString()) || [];
return;
}
if (folders.length === 1) {
stepMetadata.workspaceFolder = folders[0];
stepMetadata.projectList = await Jdtls.getProjects(folders[0].uri.toString());
stepMetadata.projectList = await Jdtls.getProjects(folders[0].uri.toString()) || [];
return;
}
const pickItems: IJavaProjectQuickPickItem[] = [];
const projectMap: Map<string, INodeData[]> = new Map<string, INodeData[]>();
for (const folder of folders) {
const projects: INodeData[] = await Jdtls.getProjects(folder.uri.toString());
const projects: INodeData[] = await Jdtls.getProjects(folder.uri.toString()) || [];
if (!_.isEmpty(projects)) {
pickItems.push({
label: folder.name,

Просмотреть файл

@ -24,7 +24,7 @@ export class ResolveMainClassExecutor implements IExportJarStepExecutor {
}
private async resolveMainClass(stepMetadata: IStepMetadata): Promise<boolean> {
const mainClasses: IMainClassInfo[] = await window.withProgress({
const mainClasses: IMainClassInfo[] | undefined = await window.withProgress({
location: ProgressLocation.Window,
title: "Exporting Jar : Resolving main classes...",
cancellable: true,

Просмотреть файл

@ -13,9 +13,9 @@ export class HierarchicalPackageNodeData implements INodeData {
}
public name: string;
public children = [];
public children: HierarchicalPackageNodeData[] = [];
public displayName: string;
private nodeData: INodeData = null;
private nodeData?: INodeData;
public get uri() {
return this.nodeData && this.nodeData.uri;
@ -34,11 +34,11 @@ export class HierarchicalPackageNodeData implements INodeData {
}
public get isPackage() {
return this.nodeData !== null;
return this.nodeData !== undefined;
}
public get handlerIdentifier() {
return this.nodeData.handlerIdentifier;
return this.nodeData?.handlerIdentifier;
}
private constructor(displayName: string, parentName: string) {
@ -68,7 +68,7 @@ export class HierarchicalPackageNodeData implements INodeData {
if (childNode) {
childNode.addSubPackage(packages, nodeData);
} else {
const newNode = new HierarchicalPackageNodeData(subPackageDisplayName, this.name);
const newNode = new HierarchicalPackageNodeData(subPackageDisplayName as string, this.name);
newNode.addSubPackage(packages, nodeData);
this.children.push(newNode);
}

Просмотреть файл

@ -9,27 +9,27 @@ import { IMainClassInfo } from "../exportJarSteps/ResolveMainClassExecutor";
import { INodeData } from "./nodeData";
export namespace Jdtls {
export function getProjects(params: string): Thenable<INodeData[]> {
export function getProjects(params: string): Thenable<INodeData[] | undefined> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_LIST, params);
}
export function refreshLibraries(params: string): Thenable<boolean> {
export function refreshLibraries(params: string): Thenable<boolean | undefined> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_REFRESH_LIB_SERVER, params);
}
export function getPackageData(params): Thenable<INodeData[]> {
export function getPackageData(params: {[key: string]: any}): Thenable<INodeData[] | undefined> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_GETPACKAGEDATA, params);
}
export function resolvePath(params: string): Thenable<INodeData[]> {
export function resolvePath(params: string): Thenable<INodeData[] | undefined> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_RESOLVEPATH, params);
}
export function getMainClasses(params: string): Thenable<IMainClassInfo[]> {
export function getMainClasses(params: string): Thenable<IMainClassInfo[] | undefined> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_GETMAINCLASSES, params);
}
export function exportJar(mainClass: string, classpaths: IClasspath[], destination: string): Thenable<IExportResult> {
export function exportJar(mainClass: string, classpaths: IClasspath[], destination: string): Thenable<IExportResult | undefined> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_GENERATEJAR,
mainClass, classpaths, destination);
}

Просмотреть файл

@ -91,15 +91,15 @@ export class Settings {
}
public static showMembers(): boolean {
return this._dependencyConfig.get("showMembers");
return this._dependencyConfig.get("showMembers", false);
}
public static autoRefresh(): boolean {
return this._dependencyConfig.get("autoRefresh");
return this._dependencyConfig.get("autoRefresh", true);
}
public static syncWithFolderExplorer(): boolean {
return this._dependencyConfig.get("syncWithFolderExplorer");
return this._dependencyConfig.get("syncWithFolderExplorer", true);
}
public static isHierarchicalView(): boolean {
@ -107,7 +107,7 @@ export class Settings {
}
public static refreshDelay(): number {
return this._dependencyConfig.get("refreshDelay");
return this._dependencyConfig.get("refreshDelay", 2000);
}
public static getExportJarTargetPath(): string {

Просмотреть файл

@ -18,7 +18,7 @@ class SyncHandler implements Disposable {
private disposables: Disposable[] = [];
public updateFileWatcher(autoRefresh: boolean): void {
public updateFileWatcher(autoRefresh?: boolean): void {
if (autoRefresh) {
instrumentOperation(ENABLE_AUTO_REFRESH, () => this.enableAutoRefresh())();
} else {
@ -64,7 +64,7 @@ class SyncHandler implements Disposable {
}
private getParentNodeInExplorer(uri: Uri): ExplorerNode {
private getParentNodeInExplorer(uri: Uri): ExplorerNode | undefined {
let node: DataNode | undefined = explorerNodeCache.findBestMatchNodeByUri(uri);
if (!node) {
@ -80,7 +80,7 @@ class SyncHandler implements Disposable {
return node;
} else {
// in flat view
if (path.extname(uri.fsPath) === ".java" &&
if (path.extname(uri.fsPath) === ".java" && node.uri &&
Uri.parse(node.uri).fsPath === path.dirname(uri.fsPath)) {
// if the returned node is direct parent of the input uri, refresh it.
return node;

Просмотреть файл

@ -19,9 +19,9 @@ export class PrimaryTypeNode extends DataNode {
super(nodeData, parent);
}
protected async loadData(): Promise<SymbolInformation[] | DocumentSymbol[]> {
if (!this.hasChildren()) {
return null;
protected async loadData(): Promise<SymbolInformation[] | DocumentSymbol[] | undefined> {
if (!this.hasChildren() || !this.nodeData.uri) {
return undefined;
}
return workspace.openTextDocument(Uri.parse(this.nodeData.uri)).then((doc) => {
@ -49,7 +49,7 @@ export class PrimaryTypeNode extends DataNode {
}
protected get iconPath(): string | ThemeIcon {
switch (this.nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
switch (this.nodeData.metaData?.[PrimaryTypeNode.K_TYPE_KIND]) {
case TypeKind.Enum:
return new ThemeIcon("symbol-enum");
case TypeKind.Interface:
@ -63,7 +63,7 @@ export class PrimaryTypeNode extends DataNode {
return Settings.showMembers();
}
private async getSymbols(document: TextDocument): Promise<SymbolInformation[] | DocumentSymbol[]> {
private async getSymbols(document: TextDocument): Promise<SymbolInformation[] | DocumentSymbol[] | undefined> {
let error;
const operationId = createUuid();
const startAt: number = Date.now();
@ -92,7 +92,7 @@ export class PrimaryTypeNode extends DataNode {
protected get contextValue(): string {
const context = Explorer.ContextValueType.Type;
const type = this.nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND];
const type = this.nodeData.metaData?.[PrimaryTypeNode.K_TYPE_KIND];
if (type === TypeKind.Enum) {
return `${context}+enum`;

Просмотреть файл

@ -8,6 +8,7 @@ import { INodeData, NodeKind } from "../java/nodeData";
import { DataNode } from "./dataNode";
import { ExplorerNode } from "./explorerNode";
import { NodeFactory } from "./nodeFactory";
import { PackageRootNode } from "./packageRootNode";
import { ProjectNode } from "./projectNode";
export class ContainerNode extends DataNode {
@ -16,14 +17,14 @@ export class ContainerNode extends DataNode {
}
public get projectBasePath() {
return Uri.parse(this._project.uri).fsPath;
return this._project.uri && Uri.parse(this._project.uri).fsPath;
}
protected loadData(): Thenable<INodeData[]> {
protected loadData(): Thenable<INodeData[] | undefined> {
return Jdtls.getPackageData({ kind: NodeKind.Container, projectUri: this._project.uri, path: this.path });
}
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const result: PackageRootNode[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.sort();
this.nodeData.children.forEach((classpathNode) => {

Просмотреть файл

@ -13,23 +13,20 @@ export abstract class DataNode extends ExplorerNode {
protected _lock: Lock = new Lock();
constructor(protected _nodeData: INodeData, parent: DataNode) {
constructor(protected _nodeData: INodeData, parent?: DataNode) {
super(parent);
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
if (this._nodeData) {
const item = new TreeItem(
this._nodeData.displayName || this._nodeData.name,
this.hasChildren() ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None,
);
item.description = this.description;
item.iconPath = this.iconPath;
item.command = this.command;
item.contextValue = this.computeContextValue();
return item;
}
return undefined;
const item = new TreeItem(
this._nodeData.displayName || this._nodeData.name,
this.hasChildren() ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None,
);
item.description = this.description;
item.iconPath = this.iconPath;
item.command = this.command;
item.contextValue = this.computeContextValue();
return item;
}
public get nodeData(): INodeData {
@ -52,14 +49,14 @@ export abstract class DataNode extends ExplorerNode {
return this._nodeData.name;
}
public async revealPaths(paths: INodeData[]): Promise<DataNode> {
public async revealPaths(paths: INodeData[]): Promise<DataNode | undefined> {
if (_.isEmpty(paths)) {
return this;
}
const childNodeData = paths.shift();
const children: ExplorerNode[] = await this.getChildren();
const childNode = children ? <DataNode>children.find((child: DataNode) =>
child.nodeData.name === childNodeData.name && child.path === childNodeData.path) : undefined;
const childNode = <DataNode>children?.find((child: DataNode) =>
child.nodeData.name === childNodeData?.name && child.path === childNodeData?.path);
return (childNode && paths.length) ? childNode.revealPaths(paths) : childNode;
}
@ -69,7 +66,7 @@ export abstract class DataNode extends ExplorerNode {
if (!this._nodeData.children) {
const data = await this.loadData();
this._nodeData.children = data;
this._childrenNodes = this.createChildNodeList();
this._childrenNodes = this.createChildNodeList() || [];
return this._childrenNodes;
}
return this._childrenNodes;
@ -78,7 +75,7 @@ export abstract class DataNode extends ExplorerNode {
}
}
public computeContextValue(): string {
public computeContextValue(): string | undefined {
let contextValue = this.contextValue;
if (this.uri && this.uri.startsWith("file:")) {
contextValue = `${contextValue || ""}+uri`;
@ -90,7 +87,7 @@ export abstract class DataNode extends ExplorerNode {
}
protected sort() {
this.nodeData.children.sort((a: INodeData, b: INodeData) => {
this.nodeData.children?.sort((a: INodeData, b: INodeData) => {
if (a.kind === b.kind) {
return a.name < b.name ? -1 : 1;
} else {
@ -103,17 +100,17 @@ export abstract class DataNode extends ExplorerNode {
return true;
}
protected get description(): string | boolean {
protected get description(): string | boolean | undefined {
return undefined;
}
protected get contextValue(): string {
protected get contextValue(): string | undefined {
return undefined;
}
protected abstract get iconPath(): string | Uri | { light: string | Uri; dark: string | Uri } | ThemeIcon;
protected abstract loadData(): Thenable<any[]>;
protected abstract loadData(): Thenable<any[] | undefined>;
protected abstract createChildNodeList(): ExplorerNode[];
protected abstract createChildNodeList(): ExplorerNode[] | undefined;
}

Просмотреть файл

@ -30,7 +30,7 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
// tslint:disable-next-line:member-ordering
public onDidChangeTreeData: Event<ExplorerNode | null | undefined> = this._onDidChangeTreeData.event;
private _rootItems: ExplorerNode[] = null;
private _rootItems: ExplorerNode[] | undefined = undefined;
private _refreshDelayTrigger: _.DebouncedFunc<((element?: ExplorerNode) => void)>;
constructor(public readonly context: ExtensionContext) {
@ -98,7 +98,7 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
return element.getTreeItem();
}
public async getChildren(element?: ExplorerNode): Promise<ExplorerNode[]> {
public async getChildren(element?: ExplorerNode): Promise<ExplorerNode[] | undefined | null> {
if (await languageServerApiManager.isLightWeightMode()) {
return [];
}
@ -109,9 +109,10 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
});
}
const children: ExplorerNode[] = (!this._rootItems || !element) ?
const children = (!this._rootItems || !element) ?
await this.getRootNodes() : await element.getChildren();
explorerNodeCache.saveNodes(children);
explorerNodeCache.saveNodes(children || []);
return children;
}
@ -119,12 +120,12 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
return element.getParent();
}
public async revealPaths(paths: INodeData[]): Promise<DataNode> {
public async revealPaths(paths: INodeData[]): Promise<DataNode | undefined> {
const projectNodeData = paths.shift();
const projects = await this.getRootProjects();
const project = projects ? <DataNode>projects.find((node: DataNode) =>
node.path === projectNodeData.path && node.nodeData.name === projectNodeData.name) : undefined;
return project ? project.revealPaths(paths) : null;
node.path === projectNodeData?.path && node.nodeData.name === projectNodeData?.name) : undefined;
return project ? project.revealPaths(paths) : undefined;
}
private doRefresh(element?: ExplorerNode): void {
@ -140,10 +141,12 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
if (rootElements[0] instanceof ProjectNode) {
return rootElements;
} else {
let result = [];
let result: ExplorerNode[] = [];
for (const rootWorkspace of rootElements) {
const projects = await rootWorkspace.getChildren();
result = result.concat(projects);
if (projects) {
result = result.concat(projects);
}
}
return result;
}
@ -165,13 +168,13 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
name: folder.name,
uri: folder.uri.toString(),
kind: NodeKind.Workspace,
}, null)));
}, undefined)));
this._rootItems = rootItems;
return rootItems;
} else {
const result: INodeData[] = await Jdtls.getProjects(folders[0].uri.toString());
result.forEach((project) => {
rootItems.push(new ProjectNode(project, null));
const result: INodeData[] | undefined = await Jdtls.getProjects(folders[0].uri.toString());
result?.forEach((project) => {
rootItems.push(new ProjectNode(project, undefined));
});
this._rootItems = rootItems;
return rootItems;

Просмотреть файл

@ -146,7 +146,7 @@ export class DependencyExplorer implements Disposable {
let node: DataNode | undefined = explorerNodeCache.getDataNode(uri);
if (!node) {
const paths: INodeData[] = await Jdtls.resolvePath(uri.toString());
const paths: INodeData[] = await Jdtls.resolvePath(uri.toString()) || [];
if (!_.isEmpty(paths)) {
node = await this._dataProvider.revealPaths(paths);
}

Просмотреть файл

@ -23,15 +23,12 @@ export class DocumentSymbolNode extends BaseSymbolNode {
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
if (this.symbolInfo) {
const item = new TreeItem(this.symbolInfo.name,
((<DocumentSymbol>this.symbolInfo).children && (<DocumentSymbol>this.symbolInfo).children.length)
? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None);
item.iconPath = this.iconPath;
item.command = this.command;
return item;
}
return undefined;
const item = new TreeItem(this.symbolInfo.name,
((<DocumentSymbol>this.symbolInfo).children && (<DocumentSymbol>this.symbolInfo).children.length)
? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None);
item.iconPath = this.iconPath;
item.command = this.command;
return item;
}
protected get range(): Range {

Просмотреть файл

@ -5,14 +5,14 @@ import { Command, ProviderResult, TreeItem } from "vscode";
export abstract class ExplorerNode {
constructor(private _parent: ExplorerNode) {
constructor(private _parent?: ExplorerNode) {
}
public getParent(): ExplorerNode {
public getParent(): ExplorerNode | undefined {
return this._parent;
}
protected get command(): Command {
protected get command(): Command | undefined {
return undefined;
}

Просмотреть файл

@ -17,12 +17,12 @@ export class FileNode extends DataNode {
return false;
}
protected loadData(): Thenable<INodeData[]> {
return Promise.resolve(null);
protected loadData(): Thenable<INodeData[] | undefined> {
return Promise.resolve(undefined);
}
protected createChildNodeList(): ExplorerNode[] {
return null;
protected createChildNodeList(): ExplorerNode[] | undefined {
return undefined;
}
protected get iconPath(): ThemeIcon {

Просмотреть файл

@ -15,7 +15,7 @@ export class FolderNode extends DataNode {
super(nodeData, parent);
}
protected loadData(): Thenable<INodeData[]> {
protected loadData(): Thenable<INodeData[] | undefined> {
return Jdtls.getPackageData({
kind: NodeKind.Folder,
projectUri: this._project.uri,
@ -25,7 +25,7 @@ export class FolderNode extends DataNode {
}
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const result: ExplorerNode[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.sort();
this.nodeData.children.forEach((nodeData) => {

Просмотреть файл

@ -19,12 +19,9 @@ export class HierarchicalPackageNode extends PackageNode {
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
if (this._nodeData) {
const item = new TreeItem(this.getHierarchicalNodeData().displayName,
const item = new TreeItem(this.getHierarchicalNodeData().displayName,
this.hasChildren() ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None);
return { ...super.getTreeItem(), ...item };
}
return undefined;
return { ...super.getTreeItem(), ...item };
}
public async getChildren(): Promise<ExplorerNode[]> {
@ -45,7 +42,7 @@ export class HierarchicalPackageNode extends PackageNode {
}
}
public async revealPaths(paths: INodeData[]): Promise<DataNode> {
public async revealPaths(paths: INodeData[]): Promise<DataNode | undefined> {
const hierarchicalNodeData = paths[0];
if (hierarchicalNodeData.name === this.nodeData.name) {
paths.shift();
@ -55,17 +52,17 @@ export class HierarchicalPackageNode extends PackageNode {
const children: ExplorerNode[] = await this.getChildren();
const childNode = <DataNode>children.find((child: DataNode) =>
hierarchicalNodeData.name.startsWith(child.nodeData.name + ".") || hierarchicalNodeData.name === child.nodeData.name);
return childNode ? childNode.revealPaths(paths) : null;
return childNode ? childNode.revealPaths(paths) : undefined;
}
}
protected loadData(): Thenable<any[]> {
protected loadData(): Thenable<any[] | undefined> {
// Load data only when current node is a package
return this.getHierarchicalNodeData().isPackage ? super.loadData() : Promise.resolve([]);
}
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const result: ExplorerNode[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.sort();
this.nodeData.children.forEach((nodeData) => {

Просмотреть файл

@ -18,7 +18,7 @@ export class HierarchicalPackageRootNode extends PackageRootNode {
super(nodeData, parent, _project);
}
public async revealPaths(paths: INodeData[]): Promise<DataNode> {
public async revealPaths(paths: INodeData[]): Promise<DataNode | undefined> {
const hierarchicalNodeData = paths[0];
const children: ExplorerNode[] = await this.getChildren();
const childNode = <DataNode>children.find((child: DataNode) =>
@ -31,7 +31,7 @@ export class HierarchicalPackageRootNode extends PackageRootNode {
}
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const result: ExplorerNode[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.sort();
this.nodeData.children.forEach((data) => {
@ -46,22 +46,21 @@ export class HierarchicalPackageRootNode extends PackageRootNode {
}
});
}
return this.getHierarchicalPackageNodes().concat(result);
return result.concat(this.getHierarchicalPackageNodes());
}
protected getHierarchicalPackageNodes(): ExplorerNode[] {
const hierarchicalPackageNodeData = this.getHierarchicalPackageNodeData();
return hierarchicalPackageNodeData === null ? [] : hierarchicalPackageNodeData.children.map((hierarchicalChildrenNode) =>
new HierarchicalPackageNode(hierarchicalChildrenNode, this, this._project, this));
return hierarchicalPackageNodeData?.children.map((hierarchicalChildrenNode) =>
new HierarchicalPackageNode(hierarchicalChildrenNode, this, this._project, this)) || [];
}
private getHierarchicalPackageNodeData(): HierarchicalPackageNodeData {
private getHierarchicalPackageNodeData(): HierarchicalPackageNodeData | undefined {
if (this.nodeData.children && this.nodeData.children.length) {
const nodeDataList = this.nodeData.children
.filter((child) => child.kind === NodeKind.Package);
return HierarchicalPackageNodeData.createHierarchicalNodeDataByPackageList(nodeDataList);
} else {
return null;
}
return undefined;
}
}

Просмотреть файл

@ -5,14 +5,17 @@ import * as path from "path";
import { Uri } from "vscode";
export class Trie<T extends IUriData> {
private _root: TrieNode<T>;
private _root: TrieNode<T | undefined>;
constructor() {
this._root = new TrieNode(null);
this._root = new TrieNode(undefined);
}
public insert(input: T): void {
let currentNode: TrieNode<T> = this.root;
if (!input.uri) {
return;
}
let currentNode: TrieNode<T | undefined> = this.root;
const fsPath: string = Uri.parse(input.uri).fsPath;
const segments: string[] = fsPath.split(path.sep);
@ -21,7 +24,7 @@ export class Trie<T extends IUriData> {
continue;
}
if (!currentNode.children[segment]) {
currentNode.children[segment] = new TrieNode(null);
currentNode.children[segment] = new TrieNode(undefined);
}
currentNode = currentNode.children[segment];
}
@ -29,7 +32,7 @@ export class Trie<T extends IUriData> {
currentNode.value = input;
}
public find(fsPath: string, returnEarly: boolean = false): TrieNode<T> | undefined {
public find(fsPath: string, returnEarly: boolean = false): TrieNode<T | undefined> | undefined {
let currentNode = this.root;
const segments: string[] = fsPath.split(path.sep);
@ -50,9 +53,9 @@ export class Trie<T extends IUriData> {
return currentNode;
}
public findFirstAncestorNodeWithData(fsPath: string): TrieNode<T> | undefined {
let currentNode: TrieNode<T> = this.root;
let res: TrieNode<T> | undefined;
public findFirstAncestorNodeWithData(fsPath: string): TrieNode<T | undefined> | undefined {
let currentNode: TrieNode<T | undefined> = this.root;
let res: TrieNode<T | undefined> | undefined;
const segments: string[] = fsPath.split(path.sep);
for (const segment of segments) {
@ -73,17 +76,17 @@ export class Trie<T extends IUriData> {
return res;
}
public get root(): TrieNode<T> {
public get root(): TrieNode<T | undefined> {
return this._root;
}
}
export interface IUriData {
uri: string;
uri?: string;
}
export class TrieNode<T> {
private _value: T;
private _value?: T;
private _children: INodeChildren<T>;
constructor(value: T) {
@ -99,7 +102,7 @@ export class TrieNode<T> {
this._children = children;
}
public set value(value: T) {
public set value(value: T | undefined) {
this._value = value;
}

Просмотреть файл

@ -22,7 +22,7 @@ class ExplorerNodeCache {
*/
public findBestMatchNodeByUri(uri: Uri): DataNode | undefined {
const parentDir = path.dirname(uri.fsPath);
const ancestor: TrieNode<DataNode> = this.mutableNodeCache.findFirstAncestorNodeWithData(parentDir);
const ancestor = this.mutableNodeCache.findFirstAncestorNodeWithData(parentDir);
return ancestor?.value;
}
@ -38,23 +38,23 @@ class ExplorerNodeCache {
}
}
public removeNodeChildren(node: ExplorerNode): void {
public removeNodeChildren(node?: ExplorerNode): void {
if (!node) {
this.removeChildren(this.mutableNodeCache.root);
return;
}
if (!(node instanceof DataNode)) {
if (!(node instanceof DataNode) || !node.uri) {
return;
}
const trieNode: TrieNode<DataNode> | undefined = this.mutableNodeCache.find(Uri.parse(node.uri).fsPath);
const trieNode = this.mutableNodeCache.find(Uri.parse(node.uri).fsPath);
if (trieNode) {
this.removeChildren(trieNode);
}
}
private removeChildren(trieNode: TrieNode<DataNode>) {
private removeChildren(trieNode: TrieNode<DataNode | undefined>) {
trieNode.children = {};
if (trieNode.value?.nodeData?.children) {
trieNode.value.nodeData.children = undefined;

Просмотреть файл

@ -16,7 +16,7 @@ export class PackageNode extends DataNode {
super(nodeData, parent);
}
protected loadData(): Thenable<INodeData[]> {
protected loadData(): Thenable<INodeData[] | undefined> {
return Jdtls.getPackageData({
kind: NodeKind.Package,
projectUri: this._project.nodeData.uri,
@ -26,7 +26,7 @@ export class PackageNode extends DataNode {
}
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const result: ExplorerNode[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.sort();
this.nodeData.children.forEach((nodeData) => {
@ -46,7 +46,7 @@ export class PackageNode extends DataNode {
return new ThemeIcon("symbol-package");
}
protected get contextValue(): string {
protected get contextValue(): string | undefined {
const parentData = <IPackageRootNodeData> this._rootNode.nodeData;
if (parentData.entryKind === PackageRootKind.K_SOURCE || parentData.kind === NodeKind.Project) {
return `${Explorer.ContextValueType.Package}+source`;

Просмотреть файл

@ -21,7 +21,7 @@ export class PackageRootNode extends DataNode {
super(nodeData, parent);
}
protected loadData(): Thenable<INodeData[]> {
protected loadData(): Thenable<INodeData[] | undefined> {
return Jdtls.getPackageData({
kind: NodeKind.PackageRoot,
projectUri: this._project.nodeData.uri,
@ -31,7 +31,7 @@ export class PackageRootNode extends DataNode {
}
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const result: ExplorerNode[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.sort();
this.nodeData.children.forEach((data: INodeData) => {
@ -51,7 +51,7 @@ export class PackageRootNode extends DataNode {
return result;
}
protected get description(): string | boolean {
protected get description(): string | boolean | undefined {
const data = <IPackageRootNodeData>this.nodeData;
if (data.entryKind === PackageRootKind.K_BINARY) {
return data.path;
@ -65,7 +65,7 @@ export class PackageRootNode extends DataNode {
if (data.entryKind === PackageRootKind.K_BINARY) {
let contextValue: string = Explorer.ContextValueType.Jar;
const parent = <ContainerNode>this.getParent();
if (parent.path.startsWith("REFERENCED_LIBRARIES_PATH")) {
if (parent.path?.startsWith("REFERENCED_LIBRARIES_PATH")) {
contextValue += "+referencedLibrary";
}
return contextValue;

Просмотреть файл

@ -18,11 +18,15 @@ import { PrimaryTypeNode } from "./PrimaryTypeNode";
export class ProjectNode extends DataNode {
constructor(nodeData: INodeData, parent: DataNode) {
constructor(nodeData: INodeData, parent?: DataNode) {
super(nodeData, parent);
}
public async revealPaths(paths: INodeData[]): Promise<DataNode> {
public async revealPaths(paths: INodeData[]): Promise<DataNode | undefined> {
if (!this.uri) {
return undefined;
}
if (workspace.getWorkspaceFolder(Uri.parse(this.uri))) {
return super.revealPaths(paths);
}
@ -48,7 +52,7 @@ export class ProjectNode extends DataNode {
return (childNode && paths.length > 0) ? childNode.revealPaths(paths) : childNode;
}
protected loadData(): Thenable<INodeData[]> {
protected loadData(): Thenable<INodeData[] | undefined> {
let result: INodeData[] = [];
return Jdtls.getPackageData({ kind: NodeKind.Project, projectUri: this.nodeData.uri }).then((res) => {
if (!res) {
@ -69,7 +73,13 @@ export class ProjectNode extends DataNode {
if (!rootPackages) {
return undefined;
}
result = result.concat(...rootPackages);
const packages: INodeData[][] = [];
for (const root of rootPackages) {
if (root !== undefined) {
packages.push(root);
}
}
result = result.concat(...packages);
return result;
});
} else {
@ -80,8 +90,8 @@ export class ProjectNode extends DataNode {
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const packageData = [];
const result: ExplorerNode[] = [];
const packageData: any[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.nodeData.children.forEach((data) => {
if (data.kind === NodeKind.Container) {
@ -105,7 +115,7 @@ export class ProjectNode extends DataNode {
if (packageData.length > 0) {
if (Settings.isHierarchicalView()) {
const data: HierarchicalPackageNodeData = HierarchicalPackageNodeData.createHierarchicalNodeDataByPackageList(packageData);
const hierarchicalPackageNodes: HierarchicalPackageNode[] = data === null ? [] : data.children.map((hierarchicalChildrenNode) =>
const hierarchicalPackageNodes: HierarchicalPackageNode[] = data === undefined ? [] : data.children.map((hierarchicalChildrenNode) =>
new HierarchicalPackageNode(hierarchicalChildrenNode, this, this, this));
result.push(...hierarchicalPackageNodes);
} else {
@ -126,7 +136,7 @@ export class ProjectNode extends DataNode {
protected get contextValue(): string {
let contextValue: string = Explorer.ContextValueType.Project;
const natureIds: string[] | undefined = this.nodeData.metaData[NATURE_ID];
const natureIds: string[] | undefined = this.nodeData.metaData?.[NATURE_ID];
if (natureIds) {
const attributeString: string = getProjectTypeAttributes(natureIds);
contextValue += attributeString;

Просмотреть файл

@ -8,7 +8,7 @@ import { ExplorerNode } from "./explorerNode";
import { PrimaryTypeNode } from "./PrimaryTypeNode";
export class SymbolNode extends BaseSymbolNode {
private _children: SymbolInformation[];
private _children?: SymbolInformation[];
constructor(symbolInfo: SymbolInformation, parent: PrimaryTypeNode) {
super(symbolInfo, parent);
@ -25,18 +25,15 @@ export class SymbolNode extends BaseSymbolNode {
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
if (this.symbolInfo) {
const parentData = <ITypeRootNodeData>(<PrimaryTypeNode>this.getParent()).nodeData;
if (parentData && parentData.symbolTree) {
this._children = parentData.symbolTree.get(this.symbolInfo.name);
}
const item = new TreeItem(this.symbolInfo.name,
(this._children && this._children.length) ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None);
item.iconPath = this.iconPath;
item.command = this.command;
return item;
const parentData = <ITypeRootNodeData>(<PrimaryTypeNode>this.getParent()).nodeData;
if (parentData && parentData.symbolTree) {
this._children = parentData.symbolTree.get(this.symbolInfo.name);
}
return undefined;
const item = new TreeItem(this.symbolInfo.name,
(this._children && this._children.length) ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None);
item.iconPath = this.iconPath;
item.command = this.command;
return item;
}
protected get range(): Range {

Просмотреть файл

@ -10,16 +10,19 @@ import { ExplorerNode } from "./explorerNode";
import { ProjectNode } from "./projectNode";
export class WorkspaceNode extends DataNode {
constructor(nodeData: INodeData, parent: DataNode) {
constructor(nodeData: INodeData, parent?: DataNode) {
super(nodeData, parent);
}
protected loadData(): Thenable<INodeData[]> {
protected loadData(): Thenable<INodeData[] | undefined> {
if (!this.nodeData.uri) {
return Promise.resolve(undefined);
}
return Jdtls.getProjects(this.nodeData.uri);
}
protected createChildNodeList(): ExplorerNode[] {
const result = [];
const result: ExplorerNode[] = [];
if (this.nodeData.children && this.nodeData.children.length) {
this.nodeData.children.forEach((nodeData) => {
result.push(new ProjectNode(nodeData, this));

Просмотреть файл

@ -16,8 +16,8 @@ suite("Gradle Project View Tests", () => {
// validate root nodes
const roots = await explorer.dataProvider.getChildren();
assert.equal(roots.length, 1, "Number of root node should be 1");
const projectNode = roots[0] as ProjectNode;
assert.equal(roots?.length, 1, "Number of root node should be 1");
const projectNode = roots![0] as ProjectNode;
assert.equal(projectNode.name, "gradle", "Project name should be \"gradle\"");
// validate package root/dependency nodes
@ -41,7 +41,7 @@ suite("Gradle Project View Tests", () => {
test("Can node have correct uri", async function() {
const explorer = DependencyExplorer.getInstance(contextManager.context);
const projectNode = (await explorer.dataProvider.getChildren())[0] as ProjectNode;
const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode;
const mainPackage = (await projectNode.getChildren())[0] as PackageRootNode;
const mainClass = (await mainPackage.getChildren())[0] as PrimaryTypeNode;

Просмотреть файл

@ -16,8 +16,8 @@ suite("Maven Project View Tests", () => {
// validate root nodes
const roots = await explorer.dataProvider.getChildren();
assert.equal(roots.length, 1, "Number of root node should be 1");
const projectNode = roots[0] as ProjectNode;
assert.equal(roots?.length, 1, "Number of root node should be 1");
const projectNode = roots![0] as ProjectNode;
assert.equal(projectNode.name, "my-app", "Project name should be \"my-app\"");
// validate package root/dependency nodes
@ -57,7 +57,7 @@ suite("Maven Project View Tests", () => {
test("Can node have correct uri", async function() {
const explorer = DependencyExplorer.getInstance(contextManager.context);
const projectNode = (await explorer.dataProvider.getChildren())[0] as ProjectNode;
const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode;
const packageRoots = await projectNode.getChildren();
const mainPackage = packageRoots[0] as PackageRootNode;
const testPackage = packageRoots[1] as PackageRootNode;

Просмотреть файл

@ -16,8 +16,8 @@ suite("Simple Project View Tests", () => {
// validate root nodes
const roots = await explorer.dataProvider.getChildren();
assert.equal(roots.length, 1, "Number of root node should be 1");
const projectNode = roots[0] as ProjectNode;
assert.equal(roots?.length, 1, "Number of root node should be 1");
const projectNode = roots![0] as ProjectNode;
assert.equal(projectNode.name, "1.helloworld", "Project name should be \"1.helloworld\"");
// validate package root/dependency nodes
@ -39,7 +39,7 @@ suite("Simple Project View Tests", () => {
test("Can node have correct uri", async function() {
const explorer = DependencyExplorer.getInstance(contextManager.context);
const projectNode = (await explorer.dataProvider.getChildren())[0] as ProjectNode;
const projectNode = (await explorer.dataProvider.getChildren())![0] as ProjectNode;
const mainPackage = (await projectNode.getChildren())[0] as PackageRootNode;
const mainClass = (await mainPackage.getChildren())[0] as PrimaryTypeNode;

Просмотреть файл

@ -88,7 +88,7 @@ const workspace: WorkspaceNode = new WorkspaceNode({
name: "workspace",
uri: Uri.file(__dirname).toString(),
kind: NodeKind.Workspace,
}, null);
}, undefined);
const mavenProject: ProjectNode = new ProjectNode({
name: "mavenProject",

Просмотреть файл

@ -10,8 +10,10 @@
"rootDir": ".",
"noUnusedLocals": true,
"noImplicitThis": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"alwaysStrict": true
},
"exclude": [