chore: cleanup

This commit is contained in:
Nathan Walker
2020-07-06 14:25:11 -07:00
parent 94cf5c4706
commit 6336eac4b5
477 changed files with 59087 additions and 74961 deletions

View File

@@ -2,18 +2,16 @@
* Provides ModuleNameResolver class used for loading files based on device capabilities.
*/ /** */
import { PlatformContext } from "./qualifier-matcher";
// export { PlatformContext } from "./qualifier-matcher";
import { PlatformContext } from './qualifier-matcher';
export { PlatformContext } from './qualifier-matcher';
export type ModuleListProvider = () => string[];
export class ModuleNameResolver {
constructor(
context: PlatformContext,
moduleListProvider?: ModuleListProvider
);
resolveModuleName(path: string, ext: string): string;
clearCache(): void;
constructor(context: PlatformContext, moduleListProvider?: ModuleListProvider);
resolveModuleName(path: string, ext: string): string;
clearCache(): void;
}
export function resolveModuleName(path: string, ext: string): string;

View File

@@ -1,123 +1,108 @@
import { ModuleNameResolver as ModuleNameResolverDefinition } from "./";
import { screen, device } from "../platform";
import * as appCommonModule from "../application/application-common";
import {
PlatformContext,
findMatch,
stripQualifiers,
} from "./qualifier-matcher";
import { registerModulesFromFileSystem } from "./non-bundle-workflow-compat";
import { Trace } from "../trace";
import { ModuleNameResolver as ModuleNameResolverDefinition } from './';
import { screen, device } from '../platform';
import * as appCommonModule from '../application/application-common';
import { PlatformContext, findMatch, stripQualifiers } from './qualifier-matcher';
import { registerModulesFromFileSystem } from './non-bundle-workflow-compat';
import { Trace } from '../trace';
export { PlatformContext } from './qualifier-matcher';
export type ModuleListProvider = () => string[];
export class ModuleNameResolver implements ModuleNameResolverDefinition {
private _cache = {};
private _cache = {};
constructor(
private context: PlatformContext,
private moduleListProvider: ModuleListProvider = global.getRegisteredModules
) {}
constructor(private context: PlatformContext, private moduleListProvider: ModuleListProvider = global.getRegisteredModules) {}
public resolveModuleName(path: string, ext: string): string {
const key = path + ext;
let result: string = this._cache[key];
if (result === undefined) {
result = this.resolveModuleNameImpl(path, ext);
this._cache[key] = result;
}
public resolveModuleName(path: string, ext: string): string {
const key = path + ext;
let result: string = this._cache[key];
if (result === undefined) {
result = this.resolveModuleNameImpl(path, ext);
this._cache[key] = result;
}
if (Trace.isEnabled()) {
Trace.write(
`path: '${path}' with ext: '${ext}' resolved: '${result}'`,
Trace.categories.ModuleNameResolver
);
}
if (Trace.isEnabled()) {
Trace.write(`path: '${path}' with ext: '${ext}' resolved: '${result}'`, Trace.categories.ModuleNameResolver);
}
return result;
}
return result;
}
public clearCache(): void {
this._cache = {};
}
public clearCache(): void {
this._cache = {};
}
private resolveModuleNameImpl(path: string, ext: string): string {
let result: string = null;
ext = ext ? "." + ext : "";
private resolveModuleNameImpl(path: string, ext: string): string {
let result: string = null;
ext = ext ? '.' + ext : '';
// Compatibility path for non-webpack workflow
// register modules from FS first
if (!global.TNS_WEBPACK) {
registerModulesFromFileSystem(path);
}
// Compatibility path for non-webpack workflow
// register modules from FS first
if (!global.TNS_WEBPACK) {
registerModulesFromFileSystem(path);
}
// This call will return a clean path without qualifiers
path = stripQualifiers(path);
// This call will return a clean path without qualifiers
path = stripQualifiers(path);
let candidates = this.getCandidates(path, ext);
result = findMatch(path, ext, candidates, this.context);
let candidates = this.getCandidates(path, ext);
result = findMatch(path, ext, candidates, this.context);
return result;
}
return result;
}
private getCandidates(path: string, ext: string): Array<string> {
const candidates = this.moduleListProvider().filter(
(moduleName) =>
moduleName.startsWith(path) &&
(!ext || moduleName.endsWith(ext))
);
private getCandidates(path: string, ext: string): Array<string> {
const candidates = this.moduleListProvider().filter((moduleName) => moduleName.startsWith(path) && (!ext || moduleName.endsWith(ext)));
return candidates;
}
return candidates;
}
}
let resolverInstance: ModuleNameResolver;
export function resolveModuleName(path: string, ext: string): string {
if (global.__snapshot) {
return resolveModuleSnapshot(path, ext);
}
if (global.__snapshot) {
return resolveModuleSnapshot(path, ext);
}
if (!resolverInstance) {
resolverInstance = new ModuleNameResolver({
width: screen.mainScreen.widthDIPs,
height: screen.mainScreen.heightDIPs,
os: device.os,
deviceType: device.deviceType,
});
}
if (!resolverInstance) {
resolverInstance = new ModuleNameResolver({
width: screen.mainScreen.widthDIPs,
height: screen.mainScreen.heightDIPs,
os: device.os,
deviceType: device.deviceType,
});
}
return resolverInstance.resolveModuleName(path, ext);
return resolverInstance.resolveModuleName(path, ext);
}
function resolveModuleSnapshot(path, ext) {
Trace.write(
`Resolving module in SNAPSHOT context - path: '${path}' with ext: '${ext}'`,
Trace.categories.ModuleNameResolver
);
Trace.write(`Resolving module in SNAPSHOT context - path: '${path}' with ext: '${ext}'`, Trace.categories.ModuleNameResolver);
// Platform module when in snapshot. So resolve modules with default android phone.
// NB: The only module name that should ever be resolved while in snapshot is app.css, because it is
// applied explicitly in the snapshot by [NativeScriptSnapshotPlugin](https://github.com/NativeScript/nativescript-dev-webpack/blob/48b26f412fd70c19dc0b9c7763e08e9505a0ae11/plugins/NativeScriptSnapshotPlugin/index.js#L48-L56)
return new ModuleNameResolver({
width: 400,
height: 800,
os: "Android",
deviceType: "Phone",
}).resolveModuleName(path, ext);
// Platform module when in snapshot. So resolve modules with default android phone.
// NB: The only module name that should ever be resolved while in snapshot is app.css, because it is
// applied explicitly in the snapshot by [NativeScriptSnapshotPlugin](https://github.com/NativeScript/nativescript-dev-webpack/blob/48b26f412fd70c19dc0b9c7763e08e9505a0ae11/plugins/NativeScriptSnapshotPlugin/index.js#L48-L56)
return new ModuleNameResolver({
width: 400,
height: 800,
os: 'Android',
deviceType: 'Phone',
}).resolveModuleName(path, ext);
}
export function clearCache() {
if (resolverInstance) {
resolverInstance.clearCache();
}
if (resolverInstance) {
resolverInstance.clearCache();
}
}
export function _setResolver(resolver: ModuleNameResolver) {
resolverInstance = resolver;
resolverInstance = resolver;
}
appCommonModule.on("livesync", (args) => clearCache());
appCommonModule.on("orientationChanged", (args) => {
resolverInstance = undefined;
appCommonModule.on('livesync', (args) => clearCache());
appCommonModule.on('orientationChanged', (args) => {
resolverInstance = undefined;
});

View File

@@ -1,73 +1,59 @@
import * as fs from "../file-system";
import * as appCommonModule from "../application/application-common";
import { Trace } from "../trace";
import * as fs from '../file-system';
import * as appCommonModule from '../application/application-common';
import { Trace } from '../trace';
const cache = new Set<string>();
let initialized = false;
function register(name: string, loader: (name?: string) => void) {
if (Trace.isEnabled()) {
Trace.write(
`[Compat] Register module: ${name}`,
Trace.categories.ModuleNameResolver
);
}
global.registerModule(name, loader);
if (Trace.isEnabled()) {
Trace.write(`[Compat] Register module: ${name}`, Trace.categories.ModuleNameResolver);
}
global.registerModule(name, loader);
if (name.startsWith("tns_modules")) {
const nonTnsModulesName = name.substr("tns_modules".length + 1);
if (Trace.isEnabled()) {
Trace.write(
`[Compat] Register module: ${nonTnsModulesName}`,
Trace.categories.ModuleNameResolver
);
}
global.registerModule(nonTnsModulesName, loader);
}
if (name.startsWith('tns_modules')) {
const nonTnsModulesName = name.substr('tns_modules'.length + 1);
if (Trace.isEnabled()) {
Trace.write(`[Compat] Register module: ${nonTnsModulesName}`, Trace.categories.ModuleNameResolver);
}
global.registerModule(nonTnsModulesName, loader);
}
}
function processFile(file: fs.File) {
const filePathRelativeToApp = file.path.substr(
fs.knownFolders.currentApp().path.length + 1
);
const loadContent = () => file.readTextSync();
const filePathRelativeToApp = file.path.substr(fs.knownFolders.currentApp().path.length + 1);
const loadContent = () => file.readTextSync();
switch (file.extension.toLocaleLowerCase()) {
case ".js":
const noExtPath = filePathRelativeToApp.substr(
0,
filePathRelativeToApp.length - ".js".length
);
switch (file.extension.toLocaleLowerCase()) {
case '.js':
const noExtPath = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - '.js'.length);
register(filePathRelativeToApp, function () {
return global.require(file.path);
});
register(noExtPath, function () {
return global.require(file.path);
});
break;
register(filePathRelativeToApp, function () {
return global.require(file.path);
});
register(noExtPath, function () {
return global.require(file.path);
});
break;
case ".css":
register(filePathRelativeToApp, loadContent);
break;
case '.css':
register(filePathRelativeToApp, loadContent);
break;
case ".xml":
register(filePathRelativeToApp, loadContent);
break;
}
case '.xml':
register(filePathRelativeToApp, loadContent);
break;
}
if (file.name === "package.json") {
const json = global.require(file.path);
if (json.main) {
let name = filePathRelativeToApp.substr(
0,
filePathRelativeToApp.length - "package.json".length - 1
);
let requirePath = fs.path.join(file.parent.path, json.main);
if (file.name === 'package.json') {
const json = global.require(file.path);
if (json.main) {
let name = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - 'package.json'.length - 1);
let requirePath = fs.path.join(file.parent.path, json.main);
register(name, () => global.require(requirePath));
}
}
register(name, () => global.require(requirePath));
}
}
}
/**
@@ -75,34 +61,31 @@ function processFile(file: fs.File) {
* @param Folder path
*/
function processFolder(path: string): boolean {
if (cache.has(path)) {
return true;
}
cache.add(path);
if (cache.has(path)) {
return true;
}
cache.add(path);
if (Trace.isEnabled()) {
Trace.write(
`[Compat] Processing folder: ${path}`,
Trace.categories.ModuleNameResolver
);
}
if (Trace.isEnabled()) {
Trace.write(`[Compat] Processing folder: ${path}`, Trace.categories.ModuleNameResolver);
}
let folderEmpty = true;
let folderEmpty = true;
if (fs.Folder.exists(path)) {
const folder = fs.Folder.fromPath(path);
if (fs.Folder.exists(path)) {
const folder = fs.Folder.fromPath(path);
folder.eachEntity((file) => {
if (file instanceof fs.File) {
processFile(file);
folderEmpty = false;
}
folder.eachEntity((file) => {
if (file instanceof fs.File) {
processFile(file);
folderEmpty = false;
}
return true;
});
}
return true;
});
}
return !folderEmpty;
return !folderEmpty;
}
/**
@@ -111,62 +94,48 @@ function processFolder(path: string): boolean {
* @param moduleName
*/
export function registerModulesFromFileSystem(moduleName: string) {
initialize();
initialize();
let folderProcessed = false;
let parentFolderProcessed = false;
// moduleName is a folder with package.json
const path = fs.path.join(fs.knownFolders.currentApp().path, moduleName);
if (fs.Folder.exists(path)) {
folderProcessed = processFolder(path);
}
let folderProcessed = false;
let parentFolderProcessed = false;
// moduleName is a folder with package.json
const path = fs.path.join(fs.knownFolders.currentApp().path, moduleName);
if (fs.Folder.exists(path)) {
folderProcessed = processFolder(path);
}
// moduleName is file - load all files in its parent folder
const parentName = moduleName.substr(
0,
moduleName.lastIndexOf(fs.path.separator)
);
const parentFolderPath = fs.path.join(
fs.knownFolders.currentApp().path,
parentName
);
if (fs.Folder.exists(parentFolderPath)) {
parentFolderProcessed = processFolder(parentFolderPath);
}
// moduleName is file - load all files in its parent folder
const parentName = moduleName.substr(0, moduleName.lastIndexOf(fs.path.separator));
const parentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, parentName);
if (fs.Folder.exists(parentFolderPath)) {
parentFolderProcessed = processFolder(parentFolderPath);
}
// Return only if we processed the actual folder or its parent folder.
// If the parent folder is empty we should still check tns_modules
// as this might be just a name of a plugin (ex. "nativescript-ui-autocomplete")
if (folderProcessed || (parentFolderProcessed && parentName)) {
return;
}
// Return only if we processed the actual folder or its parent folder.
// If the parent folder is empty we should still check tns_modules
// as this might be just a name of a plugin (ex. "nativescript-ui-autocomplete")
if (folderProcessed || (parentFolderProcessed && parentName)) {
return;
}
// moduleName is a folder in tns_modules ex. "nativescript-ui-chart"
const tnsModulesPath = fs.path.join(
fs.knownFolders.currentApp().path,
"tns_modules",
moduleName
);
if (fs.Folder.exists(tnsModulesPath)) {
processFolder(tnsModulesPath);
}
// moduleName is a folder in tns_modules ex. "nativescript-ui-chart"
const tnsModulesPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', moduleName);
if (fs.Folder.exists(tnsModulesPath)) {
processFolder(tnsModulesPath);
}
// moduleName a file in tns_modules/plugin. Avoid traversing the whole tns_modules folder if parentName is empty
if (parentName) {
const tnsParentFolderPath = fs.path.join(
fs.knownFolders.currentApp().path,
"tns_modules",
parentName
);
if (fs.Folder.exists(tnsParentFolderPath)) {
processFolder(tnsParentFolderPath);
}
}
// moduleName a file in tns_modules/plugin. Avoid traversing the whole tns_modules folder if parentName is empty
if (parentName) {
const tnsParentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', parentName);
if (fs.Folder.exists(tnsParentFolderPath)) {
processFolder(tnsParentFolderPath);
}
}
}
function initialize() {
if (!initialized) {
appCommonModule.on("livesync", (args) => cache.clear());
initialized = true;
}
if (!initialized) {
appCommonModule.on('livesync', (args) => cache.clear());
initialized = true;
}
}

View File

@@ -3,17 +3,12 @@
*/
export interface PlatformContext {
width: number;
height: number;
os: string;
deviceType: string;
width: number;
height: number;
os: string;
deviceType: string;
}
export function findMatch(
path: string,
ext: string,
candidates: Array<string>,
context: PlatformContext
): string;
export function findMatch(path: string, ext: string, candidates: Array<string>, context: PlatformContext): string;
export function stripQualifiers(path: string): string;

View File

@@ -1,197 +1,177 @@
const MIN_WH: string = "minWH";
const MIN_W: string = "minW";
const MIN_H: string = "minH";
const MIN_WH: string = 'minWH';
const MIN_W: string = 'minW';
const MIN_H: string = 'minH';
const PRIORITY_STEP = 10000;
export interface PlatformContext {
width: number;
height: number;
os: string;
deviceType: string;
width: number;
height: number;
os: string;
deviceType: string;
}
interface QualifierSpec {
isMatch(path: string): boolean;
getMatchOccurences(path: string): Array<string>;
getMatchValue(value: string, context: PlatformContext): number;
isMatch(path: string): boolean;
getMatchOccurences(path: string): Array<string>;
getMatchValue(value: string, context: PlatformContext): number;
}
const minWidthHeightQualifier: QualifierSpec = {
isMatch: function (path: string): boolean {
return new RegExp(`.${MIN_WH}\\d+`).test(path);
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp(`.${MIN_WH}\\d+`, "g"));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_WH.length + 1));
if (isNaN(numVal)) {
return -1;
}
isMatch: function (path: string): boolean {
return new RegExp(`.${MIN_WH}\\d+`).test(path);
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp(`.${MIN_WH}\\d+`, 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_WH.length + 1));
if (isNaN(numVal)) {
return -1;
}
const actualLength = Math.min(context.width, context.height);
if (actualLength < numVal) {
return -1;
}
const actualLength = Math.min(context.width, context.height);
if (actualLength < numVal) {
return -1;
}
return PRIORITY_STEP - (actualLength - numVal);
},
return PRIORITY_STEP - (actualLength - numVal);
},
};
const minWidthQualifier: QualifierSpec = {
isMatch: function (path: string): boolean {
return (
new RegExp(`.${MIN_W}\\d+`).test(path) &&
!new RegExp(`.${MIN_WH}\\d+`).test(path)
);
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp(`.${MIN_W}\\d+`, "g"));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_W.length + 1));
if (isNaN(numVal)) {
return -1;
}
isMatch: function (path: string): boolean {
return new RegExp(`.${MIN_W}\\d+`).test(path) && !new RegExp(`.${MIN_WH}\\d+`).test(path);
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp(`.${MIN_W}\\d+`, 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_W.length + 1));
if (isNaN(numVal)) {
return -1;
}
const actualWidth = context.width;
if (actualWidth < numVal) {
return -1;
}
const actualWidth = context.width;
if (actualWidth < numVal) {
return -1;
}
return PRIORITY_STEP - (actualWidth - numVal);
},
return PRIORITY_STEP - (actualWidth - numVal);
},
};
const minHeightQualifier: QualifierSpec = {
isMatch: function (path: string): boolean {
return (
new RegExp(`.${MIN_H}\\d+`).test(path) &&
!new RegExp(`.${MIN_WH}\\d+`).test(path)
);
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp(`.${MIN_H}\\d+`, "g"));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_H.length + 1));
if (isNaN(numVal)) {
return -1;
}
isMatch: function (path: string): boolean {
return new RegExp(`.${MIN_H}\\d+`).test(path) && !new RegExp(`.${MIN_WH}\\d+`).test(path);
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp(`.${MIN_H}\\d+`, 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_H.length + 1));
if (isNaN(numVal)) {
return -1;
}
const actualHeight = context.height;
if (actualHeight < numVal) {
return -1;
}
const actualHeight = context.height;
if (actualHeight < numVal) {
return -1;
}
return PRIORITY_STEP - (actualHeight - numVal);
},
return PRIORITY_STEP - (actualHeight - numVal);
},
};
const platformQualifier: QualifierSpec = {
isMatch: function (path: string): boolean {
return path.includes(".android") || path.includes(".ios");
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp("\\.android|\\.ios", "g"));
},
getMatchValue(value: string, context: PlatformContext): number {
const val = value.substr(1);
isMatch: function (path: string): boolean {
return path.includes('.android') || path.includes('.ios');
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp('\\.android|\\.ios', 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const val = value.substr(1);
return val === context.os.toLowerCase() ? 1 : -1;
},
return val === context.os.toLowerCase() ? 1 : -1;
},
};
const orientationQualifier: QualifierSpec = {
isMatch: function (path: string): boolean {
return path.includes(".land") || path.includes(".port");
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp("\\.land|\\.port", "g"));
},
getMatchValue(value: string, context: PlatformContext): number {
const val = value.substr(1);
const isLandscape: number = context.width > context.height ? 1 : -1;
isMatch: function (path: string): boolean {
return path.includes('.land') || path.includes('.port');
},
getMatchOccurences: function (path: string): Array<string> {
return path.match(new RegExp('\\.land|\\.port', 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const val = value.substr(1);
const isLandscape: number = context.width > context.height ? 1 : -1;
return val === "land" ? isLandscape : -isLandscape;
},
return val === 'land' ? isLandscape : -isLandscape;
},
};
// List of supported qualifiers ordered by priority
const supportedQualifiers: Array<QualifierSpec> = [
minWidthHeightQualifier,
minWidthQualifier,
minHeightQualifier,
orientationQualifier,
platformQualifier,
];
const supportedQualifiers: Array<QualifierSpec> = [minWidthHeightQualifier, minWidthQualifier, minHeightQualifier, orientationQualifier, platformQualifier];
function checkQualifiers(path: string, context: PlatformContext): number {
let result = 0;
for (let i = 0; i < supportedQualifiers.length; i++) {
let qualifier = supportedQualifiers[i];
if (qualifier.isMatch(path)) {
let occurences = qualifier.getMatchOccurences(path);
// Always get the last qualifier among identical occurences
result = qualifier.getMatchValue(
occurences[occurences.length - 1],
context
);
if (result < 0) {
// Non of the supported qualifiers matched this or the match was not satisfied
return -1;
}
let result = 0;
for (let i = 0; i < supportedQualifiers.length; i++) {
let qualifier = supportedQualifiers[i];
if (qualifier.isMatch(path)) {
let occurences = qualifier.getMatchOccurences(path);
// Always get the last qualifier among identical occurences
result = qualifier.getMatchValue(occurences[occurences.length - 1], context);
if (result < 0) {
// Non of the supported qualifiers matched this or the match was not satisfied
return -1;
}
result += (supportedQualifiers.length - i) * PRIORITY_STEP;
result += (supportedQualifiers.length - i) * PRIORITY_STEP;
return result;
}
}
return result;
}
}
return result;
return result;
}
export function stripQualifiers(path: string): string {
// Strip qualifiers from path if any
for (let i = 0; i < supportedQualifiers.length; i++) {
let qualifier = supportedQualifiers[i];
if (qualifier.isMatch(path)) {
let occurences = qualifier.getMatchOccurences(path);
for (let j = 0; j < occurences.length; j++) {
path = path.replace(occurences[j], "");
}
}
}
// Strip qualifiers from path if any
for (let i = 0; i < supportedQualifiers.length; i++) {
let qualifier = supportedQualifiers[i];
if (qualifier.isMatch(path)) {
let occurences = qualifier.getMatchOccurences(path);
for (let j = 0; j < occurences.length; j++) {
path = path.replace(occurences[j], '');
}
}
}
return path;
return path;
}
export function findMatch(
path: string,
ext: string,
candidates: Array<string>,
context: PlatformContext
): string {
let fullPath: string = ext ? path + ext : path;
let bestValue = -1;
let result: string = null;
export function findMatch(path: string, ext: string, candidates: Array<string>, context: PlatformContext): string {
let fullPath: string = ext ? path + ext : path;
let bestValue = -1;
let result: string = null;
for (let i = 0; i < candidates.length; i++) {
const filePath = candidates[i];
for (let i = 0; i < candidates.length; i++) {
const filePath = candidates[i];
// Check if candidate is correct for given path
const cleanFilePath: string = stripQualifiers(filePath);
if (cleanFilePath !== fullPath) {
continue;
}
// Check if candidate is correct for given path
const cleanFilePath: string = stripQualifiers(filePath);
if (cleanFilePath !== fullPath) {
continue;
}
const value = checkQualifiers(filePath, context);
const value = checkQualifiers(filePath, context);
if (value >= 0 && value > bestValue) {
bestValue = value;
result = candidates[i];
}
}
if (value >= 0 && value > bestValue) {
bestValue = value;
result = candidates[i];
}
}
return result;
return result;
}