/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at . */
// @flow
import { endTruncateStr } from "./utils";
import {
isPretty,
getFilename,
getSourceClassnames,
getSourceQueryString,
} from "./source";
import type { Location as BabelLocation } from "@babel/types";
import type { Symbols } from "../reducers/ast";
import type { QuickOpenType } from "../reducers/quick-open";
import type { Tab } from "../reducers/tabs";
import type { Source } from "../types";
import type {
SymbolDeclaration,
IdentifierDeclaration,
} from "../workers/parser";
export const MODIFIERS = {
"@": "functions",
"#": "variables",
":": "goto",
"?": "shortcuts",
};
export function parseQuickOpenQuery(query: string): QuickOpenType {
const startsWithModifier =
query[0] === "@" ||
query[0] === "#" ||
query[0] === ":" ||
query[0] === "?";
if (startsWithModifier) {
const modifier = query[0];
return MODIFIERS[modifier];
}
const isGotoSource = query.includes(":", 1);
if (isGotoSource) {
return "gotoSource";
}
return "sources";
}
export function parseLineColumn(query: string) {
const [, line, column] = query.split(":");
const lineNumber = parseInt(line, 10);
const columnNumber = parseInt(column, 10);
if (!isNaN(lineNumber)) {
return {
line: lineNumber,
...(!isNaN(columnNumber) ? { column: columnNumber } : null),
};
}
}
export function formatSourcesForList(
source: Source,
tabUrls: Set<$PropertyType>
) {
const title = getFilename(source);
const relativeUrlWithQuery = `${source.relativeUrl}${getSourceQueryString(
source
) || ""}`;
const subtitle = endTruncateStr(relativeUrlWithQuery, 100);
const value = relativeUrlWithQuery;
return {
value,
title,
subtitle,
icon: tabUrls.has(source.url)
? "tab result-item-icon"
: `result-item-icon ${getSourceClassnames(source)}`,
id: source.id,
url: source.url,
};
}
export type QuickOpenResult = {|
id: string,
value: string,
title: string | React$Element<"div">,
subtitle?: string,
location?: BabelLocation,
url?: string,
icon?: string,
|};
export type FormattedSymbolDeclarations = {|
functions: Array,
|};
export function formatSymbol(
symbol: SymbolDeclaration | IdentifierDeclaration
): QuickOpenResult {
return {
id: `${symbol.name}:${symbol.location.start.line}`,
title: symbol.name,
subtitle: `${symbol.location.start.line}`,
value: symbol.name,
location: symbol.location,
};
}
export function formatSymbols(symbols: ?Symbols): FormattedSymbolDeclarations {
if (!symbols || symbols.loading) {
return { functions: [] };
}
const { functions } = symbols;
return {
functions: functions.map(formatSymbol),
};
}
export function formatShortcutResults(): Array {
return [
{
value: L10N.getStr("symbolSearch.search.functionsPlaceholder.title"),
title: `@ ${L10N.getStr("symbolSearch.search.functionsPlaceholder")}`,
id: "@",
},
{
value: L10N.getStr("symbolSearch.search.variablesPlaceholder.title"),
title: `# ${L10N.getStr("symbolSearch.search.variablesPlaceholder")}`,
id: "#",
},
{
value: L10N.getStr("gotoLineModal.title"),
title: `: ${L10N.getStr("gotoLineModal.placeholder")}`,
id: ":",
},
];
}
export function formatSources(
sources: Source[],
tabUrls: Set<$PropertyType>
): Array {
const formattedSources: Array = [];
for (let i = 0; i < sources.length; ++i) {
const source = sources[i];
if (!!source.relativeUrl && !isPretty(source)) {
formattedSources.push(formatSourcesForList(source, tabUrls));
}
}
return formattedSources;
}