Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(typescript-estree): fix persisted parse for relative paths #1424

Merged
merged 10 commits into from Jan 12, 2020
Expand Up @@ -395,7 +395,9 @@ function maybeInvalidateProgram(
const folderWatchCallbacks = folderWatchCallbackTrackingMap.get(current);
if (folderWatchCallbacks) {
folderWatchCallbacks.forEach(cb => {
cb(currentDir, ts.FileWatcherEventKind.Changed);
if (currentDir !== current) {
cb(currentDir, ts.FileWatcherEventKind.Changed);
}
cb(current!, ts.FileWatcherEventKind.Changed);
});
hasCallback = true;
Expand Down
13 changes: 8 additions & 5 deletions packages/typescript-estree/src/create-program/shared.ts
Expand Up @@ -38,12 +38,14 @@ function getCanonicalFileName(filePath: string): CanonicalPath {
return correctPathCasing(normalized) as CanonicalPath;
}

function ensureAbsolutePath(p: string, extra: Extra): string {
return path.isAbsolute(p)
? p
: path.join(extra.tsconfigRootDir || process.cwd(), p);
}

function getTsconfigPath(tsconfigPath: string, extra: Extra): CanonicalPath {
return getCanonicalFileName(
path.isAbsolute(tsconfigPath)
? tsconfigPath
: path.join(extra.tsconfigRootDir || process.cwd(), tsconfigPath),
);
return getCanonicalFileName(ensureAbsolutePath(tsconfigPath, extra));
}

function canonicalDirname(p: CanonicalPath): CanonicalPath {
Expand Down Expand Up @@ -84,6 +86,7 @@ export {
canonicalDirname,
CanonicalPath,
DEFAULT_COMPILER_OPTIONS,
ensureAbsolutePath,
getCanonicalFileName,
getScriptKind,
getTsconfigPath,
Expand Down
2 changes: 2 additions & 0 deletions packages/typescript-estree/src/parser.ts
Expand Up @@ -11,6 +11,7 @@ import { createSourceFile } from './create-program/createSourceFile';
import { Extra, TSESTreeOptions, ParserServices } from './parser-options';
import { getFirstSemanticOrSyntacticError } from './semantic-or-syntactic-errors';
import { TSESTree } from './ts-estree';
import { ensureAbsolutePath } from './create-program/shared';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't like this, maybe i should move it somewhere else


/**
* This needs to be kept in sync with the top-level README.md in the
Expand Down Expand Up @@ -145,6 +146,7 @@ function applyParserOptionsToExtra(options: TSESTreeOptions): void {
} else {
extra.filePath = getFileName(extra);
}
extra.filePath = ensureAbsolutePath(extra.filePath, extra);

/**
* The JSX AST changed the node type for string literals
Expand Down
39 changes: 37 additions & 2 deletions packages/typescript-estree/tests/lib/persistentParse.ts
Expand Up @@ -10,6 +10,7 @@ const CONTENTS = {
'bat/baz/bar': 'console.log("bat/baz/bar")',
};

const cwdCopy = process.cwd();
const tmpDirs = new Set<tmp.DirResult>();
afterEach(() => {
// stop watching the files and folders
Expand All @@ -18,6 +19,9 @@ afterEach(() => {
// clean up the temporary files and folders
tmpDirs.forEach(t => t.removeCallback());
tmpDirs.clear();

// restore original cwd
process.chdir(cwdCopy);
});

function writeTSConfig(dirName: string, config: Record<string, unknown>): void {
Expand Down Expand Up @@ -54,14 +58,24 @@ function setup(tsconfig: Record<string, unknown>, writeBar = true): string {
return tmpDir.name;
}

function parseFile(filename: keyof typeof CONTENTS, tmpDir: string): void {
function parseFile(
filename: keyof typeof CONTENTS,
tmpDir: string,
relative?: boolean,
): void {
parseAndGenerateServices(CONTENTS.foo, {
project: './tsconfig.json',
tsconfigRootDir: tmpDir,
filePath: path.join(tmpDir, 'src', `${filename}.ts`),
filePath: relative
? path.join('src', `${filename}.ts`)
: path.join(tmpDir, 'src', `${filename}.ts`),
});
}

function existsSync(filename: keyof typeof CONTENTS, tmpDir = ''): boolean {
return fs.existsSync(path.join(tmpDir, 'src', `${filename}.ts`));
}

function baseTests(
tsConfigExcludeBar: Record<string, unknown>,
tsConfigIncludeAll: Record<string, unknown>,
Expand Down Expand Up @@ -161,6 +175,27 @@ function baseTests(
expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow();
expect(() => parseFile('bar', PROJECT_DIR)).not.toThrow();
});

it('should work with relative paths', () => {
const PROJECT_DIR = setup(tsConfigIncludeAll, false);
process.chdir(PROJECT_DIR);

// parse once to: assert the config as correct, and to make sure the program is setup
expect(() => parseFile('foo', PROJECT_DIR, true)).not.toThrow();
// bar should throw because it doesn't exist yet
expect(() => parseFile('bar', PROJECT_DIR, true)).toThrow();

// write a new file and attempt to parse it
writeFile(PROJECT_DIR, 'bar');

// make sure that file is correctly created
expect(existsSync('bar')).toEqual(true);
expect(existsSync('bar', PROJECT_DIR)).toEqual(true);

// both files should parse fine now
expect(() => parseFile('foo', PROJECT_DIR, true)).not.toThrow();
expect(() => parseFile('bar', PROJECT_DIR, true)).not.toThrow();
});
}

describe('persistent parse', () => {
Expand Down