2019-08-23 02:05:01 +10:00
|
|
|
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
2019-10-03 21:23:29 +10:00
|
|
|
|
|
|
|
interface FileReference {
|
|
|
|
fileName: string;
|
|
|
|
pos: number;
|
2019-08-23 02:05:01 +10:00
|
|
|
end: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Remap the module name based on any supplied type directives passed. */
|
|
|
|
export function getMappedModuleName(
|
2019-10-03 21:23:29 +10:00
|
|
|
source: FileReference,
|
|
|
|
typeDirectives: Map<FileReference, string>
|
2019-08-23 02:05:01 +10:00
|
|
|
): string {
|
2019-10-03 21:23:29 +10:00
|
|
|
const { fileName: sourceFileName, pos: sourcePos } = source;
|
|
|
|
for (const [{ fileName, pos }, value] of typeDirectives.entries()) {
|
|
|
|
if (sourceFileName === fileName && sourcePos === pos) {
|
|
|
|
return value;
|
|
|
|
}
|
2019-08-23 02:05:01 +10:00
|
|
|
}
|
2019-10-03 21:23:29 +10:00
|
|
|
return source.fileName;
|
2019-08-23 02:05:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Matches directives that look something like this and parses out the value
|
|
|
|
* of the directive:
|
|
|
|
*
|
|
|
|
* // @deno-types="./foo.d.ts"
|
|
|
|
*
|
|
|
|
* [See Diagram](http://bit.ly/31nZPCF)
|
|
|
|
*/
|
|
|
|
const typeDirectiveRegEx = /@deno-types\s*=\s*(["'])((?:(?=(\\?))\3.)*?)\1/gi;
|
|
|
|
|
2019-09-11 12:47:34 +02:00
|
|
|
/** Matches `import`, `import from` or `export from` statements and parses out the value of the
|
2019-08-23 02:05:01 +10:00
|
|
|
* module specifier in the second capture group:
|
|
|
|
*
|
2019-09-11 12:47:34 +02:00
|
|
|
* import "./foo.js"
|
2019-08-23 02:05:01 +10:00
|
|
|
* import * as foo from "./foo.js"
|
|
|
|
* export { a, b, c } from "./bar.js"
|
|
|
|
*
|
2019-09-15 22:58:06 +10:00
|
|
|
* [See Diagram](http://bit.ly/2lOsp0K)
|
2019-08-23 02:05:01 +10:00
|
|
|
*/
|
2019-09-15 22:58:06 +10:00
|
|
|
const importExportRegEx = /(?:import|export)(?:\s+|\s+[\s\S]*?from\s+)?(["'])((?:(?=(\\?))\3.)*?)\1/;
|
2019-08-23 02:05:01 +10:00
|
|
|
|
|
|
|
/** Parses out any Deno type directives that are part of the source code, or
|
|
|
|
* returns `undefined` if there are not any.
|
|
|
|
*/
|
|
|
|
export function parseTypeDirectives(
|
|
|
|
sourceCode: string | undefined
|
2019-10-03 21:23:29 +10:00
|
|
|
): Map<FileReference, string> | undefined {
|
2019-08-23 02:05:01 +10:00
|
|
|
if (!sourceCode) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// collect all the directives in the file and their start and end positions
|
2019-10-03 21:23:29 +10:00
|
|
|
const directives: FileReference[] = [];
|
2019-08-23 02:05:01 +10:00
|
|
|
let maybeMatch: RegExpExecArray | null = null;
|
|
|
|
while ((maybeMatch = typeDirectiveRegEx.exec(sourceCode))) {
|
2019-10-03 21:23:29 +10:00
|
|
|
const [matchString, , fileName] = maybeMatch;
|
|
|
|
const { index: pos } = maybeMatch;
|
2019-08-23 02:05:01 +10:00
|
|
|
directives.push({
|
2019-10-03 21:23:29 +10:00
|
|
|
fileName,
|
|
|
|
pos,
|
|
|
|
end: pos + matchString.length
|
2019-08-23 02:05:01 +10:00
|
|
|
});
|
|
|
|
}
|
|
|
|
if (!directives.length) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// work from the last directive backwards for the next `import`/`export`
|
|
|
|
// statement
|
|
|
|
directives.reverse();
|
2019-10-03 21:23:29 +10:00
|
|
|
const results = new Map<FileReference, string>();
|
|
|
|
for (const { end, fileName, pos } of directives) {
|
2019-08-23 02:05:01 +10:00
|
|
|
const searchString = sourceCode.substring(end);
|
|
|
|
const maybeMatch = importExportRegEx.exec(searchString);
|
|
|
|
if (maybeMatch) {
|
2019-10-03 21:23:29 +10:00
|
|
|
const [matchString, , targetFileName] = maybeMatch;
|
|
|
|
const targetPos =
|
|
|
|
end + maybeMatch.index + matchString.indexOf(targetFileName) - 1;
|
|
|
|
const target: FileReference = {
|
|
|
|
fileName: targetFileName,
|
|
|
|
pos: targetPos,
|
|
|
|
end: targetPos + targetFileName.length
|
|
|
|
};
|
|
|
|
results.set(target, fileName);
|
2019-08-23 02:05:01 +10:00
|
|
|
}
|
2019-10-03 21:23:29 +10:00
|
|
|
sourceCode = sourceCode.substring(0, pos);
|
2019-08-23 02:05:01 +10:00
|
|
|
}
|
|
|
|
|
2019-10-03 21:23:29 +10:00
|
|
|
return results;
|
2019-08-23 02:05:01 +10:00
|
|
|
}
|