Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit 96d6c47

Browse files
committed
fix: Add tests, handle windows paths in project-manager
1 parent f0c8e02 commit 96d6c47

File tree

2 files changed

+143
-124
lines changed

2 files changed

+143
-124
lines changed

src/project-manager.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ export class ProjectManager implements Disposable {
589589

590590
// Create catch-all fallback configs in case there are no tsconfig.json files
591591
// They are removed once at least one tsconfig.json is found
592-
const trimmedRootPath = this.rootPath.replace(/\/+$/, '')
592+
const trimmedRootPath = this.rootPath.replace(/[\\\/]+$/, '')
593593
const fallbackConfigs: {js?: ProjectConfiguration, ts?: ProjectConfiguration} = {}
594594
for (const configType of ['js', 'ts'] as ConfigType[]) {
595595
const configs = this.configs[configType]
@@ -622,13 +622,8 @@ export class ProjectManager implements Disposable {
622622
.filter(([uri, content]) => !!content && /\/[tj]sconfig\.json/.test(uri) && !uri.includes('/node_modules/'))
623623
.subscribe(([uri, content]) => {
624624
const filePath = uri2path(uri)
625-
let dir = toUnixPath(filePath)
626-
const pos = dir.lastIndexOf('/')
627-
if (pos <= 0) {
628-
dir = ''
629-
} else {
630-
dir = dir.substring(0, pos)
631-
}
625+
const pos = filePath.includes('\\') ? filePath.lastIndexOf('\\') : filePath.lastIndexOf('/')
626+
const dir = pos <= 0 ? '' : filePath.substring(0, pos)
632627
const configType = this.getConfigurationType(filePath)
633628
const configs = this.configs[configType]
634629
configs.set(dir, new ProjectConfiguration(
@@ -930,19 +925,19 @@ export class ProjectManager implements Disposable {
930925
* @return closest configuration for a given file path or undefined if there is no such configuration
931926
*/
932927
public getConfigurationIfExists(filePath: string, configType = this.getConfigurationType(filePath)): ProjectConfiguration | undefined {
933-
let dir = toUnixPath(filePath)
928+
let dir = filePath
934929
let config: ProjectConfiguration | undefined
935930
const configs = this.configs[configType]
936931
if (!configs) {
937932
return undefined
938933
}
939-
const rootPath = this.rootPath.replace(/\/+$/, '')
934+
const rootPath = this.rootPath.replace(/[\\\/]+$/, '')
940935
while (dir && dir !== rootPath) {
941936
config = configs.get(dir)
942937
if (config) {
943938
return config
944939
}
945-
const pos = dir.lastIndexOf('/')
940+
const pos = dir.includes('\\') ? dir.lastIndexOf('\\') : dir.lastIndexOf('/')
946941
if (pos <= 0) {
947942
dir = ''
948943
} else {
@@ -1030,13 +1025,14 @@ export class ProjectManager implements Disposable {
10301025
* @return configuration type to use for a given file
10311026
*/
10321027
private getConfigurationType(filePath: string): ConfigType {
1033-
const name = path.posix.basename(filePath)
1028+
const unixPath = toUnixPath(filePath)
1029+
const name = path.posix.basename(unixPath)
10341030
if (name === 'tsconfig.json') {
10351031
return 'ts'
10361032
} else if (name === 'jsconfig.json') {
10371033
return 'js'
10381034
}
1039-
const extension = path.posix.extname(filePath)
1035+
const extension = path.posix.extname(unixPath)
10401036
if (extension === '.js' || extension === '.jsx') {
10411037
return 'js'
10421038
}

src/test/project-manager.test.ts

Lines changed: 134 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -3,134 +3,157 @@ import chaiAsPromised = require('chai-as-promised')
33
import { FileSystemUpdater } from '../fs'
44
import { InMemoryFileSystem } from '../memfs'
55
import { ProjectManager } from '../project-manager'
6+
import { uri2path } from '../util'
67
import { MapFileSystem } from './fs-helpers'
78
chai.use(chaiAsPromised)
89
const assert = chai.assert
910

1011
describe('ProjectManager', () => {
12+
for (const rootUri of ['file:///', 'file:///c:/foo/bar/', 'file:///foo/bar/']) {
13+
testWithRootUri(rootUri)
14+
}
15+
})
1116

12-
let projectManager: ProjectManager
13-
let memfs: InMemoryFileSystem
17+
function testWithRootUri(rootUri: string): void {
18+
describe(`with rootUri ${rootUri}`, () => {
1419

15-
it('should add a ProjectConfiguration when a tsconfig.json is added to the InMemoryFileSystem', () => {
16-
memfs = new InMemoryFileSystem('/')
17-
const localfs = new MapFileSystem(new Map([
18-
['file:///foo/tsconfig.json', '{}']
19-
]))
20-
const updater = new FileSystemUpdater(localfs, memfs)
21-
projectManager = new ProjectManager('/', memfs, updater, true)
22-
memfs.add('file:///foo/tsconfig.json', '{}')
23-
const configs = Array.from(projectManager.configurations())
24-
assert.isDefined(configs.find(config => config.configFilePath === '/foo/tsconfig.json'))
25-
})
20+
let projectManager: ProjectManager
21+
let memfs: InMemoryFileSystem
2622

27-
describe('ensureBasicFiles', () => {
28-
beforeEach(async () => {
29-
memfs = new InMemoryFileSystem('/')
23+
it('should add a ProjectConfiguration when a tsconfig.json is added to the InMemoryFileSystem', () => {
24+
const rootPath = uri2path(rootUri)
25+
memfs = new InMemoryFileSystem(rootPath)
26+
const configFileUri = rootUri + 'foo/tsconfig.json'
3027
const localfs = new MapFileSystem(new Map([
31-
['file:///project/package.json', '{"name": "package-name-1"}'],
32-
['file:///project/tsconfig.json', '{ "compilerOptions": { "typeRoots": ["../types"]} }'],
33-
['file:///project/file.ts', 'console.log(GLOBALCONSTANT);'],
34-
['file:///types/types.d.ts', 'declare var GLOBALCONSTANT=1;']
35-
28+
[configFileUri, '{}']
3629
]))
3730
const updater = new FileSystemUpdater(localfs, memfs)
38-
projectManager = new ProjectManager('/', memfs, updater, true)
39-
})
40-
it('loads files from typeRoots', async () => {
41-
await projectManager.ensureReferencedFiles('file:///project/file.ts').toPromise()
42-
memfs.getContent('file:///project/file.ts')
43-
memfs.getContent('file:///types/types.d.ts')
44-
})
45-
})
31+
projectManager = new ProjectManager(rootPath, memfs, updater, true)
32+
memfs.add(configFileUri, '{}')
33+
const configs = Array.from(projectManager.configurations())
34+
const expectedConfigFilePath = uri2path(configFileUri)
4635

47-
describe('getPackageName()', () => {
48-
beforeEach(async () => {
49-
memfs = new InMemoryFileSystem('/')
50-
const localfs = new MapFileSystem(new Map([
51-
['file:///package.json', '{"name": "package-name-1"}'],
52-
['file:///subdirectory-with-tsconfig/package.json', '{"name": "package-name-2"}'],
53-
['file:///subdirectory-with-tsconfig/src/tsconfig.json', '{}'],
54-
['file:///subdirectory-with-tsconfig/src/dummy.ts', '']
55-
]))
56-
const updater = new FileSystemUpdater(localfs, memfs)
57-
projectManager = new ProjectManager('/', memfs, updater, true)
58-
await projectManager.ensureAllFiles().toPromise()
59-
})
60-
})
61-
describe('ensureReferencedFiles()', () => {
62-
beforeEach(() => {
63-
memfs = new InMemoryFileSystem('/')
64-
const localfs = new MapFileSystem(new Map([
65-
['file:///package.json', '{"name": "package-name-1"}'],
66-
['file:///node_modules/somelib/index.js', '/// <reference path="./pathref.d.ts"/>\n/// <reference types="node"/>'],
67-
['file:///node_modules/somelib/pathref.d.ts', ''],
68-
['file:///node_modules/%40types/node/index.d.ts', ''],
69-
['file:///src/dummy.ts', 'import * as somelib from "somelib";']
70-
]))
71-
const updater = new FileSystemUpdater(localfs, memfs)
72-
projectManager = new ProjectManager('/', memfs, updater, true)
36+
assert.isDefined(configs.find(config => config.configFilePath === expectedConfigFilePath))
7337
})
74-
it('should ensure content for imports and references is fetched', async () => {
75-
await projectManager.ensureReferencedFiles('file:///src/dummy.ts').toPromise()
76-
memfs.getContent('file:///node_modules/somelib/index.js')
77-
memfs.getContent('file:///node_modules/somelib/pathref.d.ts')
78-
memfs.getContent('file:///node_modules/%40types/node/index.d.ts')
79-
})
80-
})
81-
describe('getConfiguration()', () => {
82-
beforeEach(async () => {
83-
memfs = new InMemoryFileSystem('/')
84-
const localfs = new MapFileSystem(new Map([
85-
['file:///tsconfig.json', '{}'],
86-
['file:///src/jsconfig.json', '{}']
87-
]))
88-
const updater = new FileSystemUpdater(localfs, memfs)
89-
projectManager = new ProjectManager('/', memfs, updater, true)
90-
await projectManager.ensureAllFiles().toPromise()
38+
39+
describe('ensureBasicFiles', () => {
40+
beforeEach(async () => {
41+
const rootPath = uri2path(rootUri)
42+
memfs = new InMemoryFileSystem(rootPath)
43+
const localfs = new MapFileSystem(new Map([
44+
[rootUri + 'project/package.json', '{"name": "package-name-1"}'],
45+
[rootUri + 'project/tsconfig.json', '{ "compilerOptions": { "typeRoots": ["../types"]} }'],
46+
[rootUri + 'project/file.ts', 'console.log(GLOBALCONSTANT);'],
47+
[rootUri + 'types/types.d.ts', 'declare var GLOBALCONSTANT=1;']
48+
49+
]))
50+
const updater = new FileSystemUpdater(localfs, memfs)
51+
projectManager = new ProjectManager(rootPath, memfs, updater, true)
52+
})
53+
it('loads files from typeRoots', async () => {
54+
await projectManager.ensureReferencedFiles(rootUri + 'project/file.ts').toPromise()
55+
memfs.getContent(rootUri + 'project/file.ts')
56+
memfs.getContent(rootUri + 'types/types.d.ts')
57+
})
9158
})
92-
it('should resolve best configuration based on file name', () => {
93-
const jsConfig = projectManager.getConfiguration('/src/foo.js')
94-
const tsConfig = projectManager.getConfiguration('/src/foo.ts')
95-
assert.equal('/tsconfig.json', tsConfig.configFilePath)
96-
assert.equal('/src/jsconfig.json', jsConfig.configFilePath)
59+
60+
describe('getPackageName()', () => {
61+
beforeEach(async () => {
62+
const rootPath = uri2path(rootUri)
63+
memfs = new InMemoryFileSystem(rootPath)
64+
const localfs = new MapFileSystem(new Map([
65+
[rootUri + 'package.json', '{"name": "package-name-1"}'],
66+
[rootUri + 'subdirectory-with-tsconfig/package.json', '{"name": "package-name-2"}'],
67+
[rootUri + 'subdirectory-with-tsconfig/src/tsconfig.json', '{}'],
68+
[rootUri + 'subdirectory-with-tsconfig/src/dummy.ts', '']
69+
]))
70+
const updater = new FileSystemUpdater(localfs, memfs)
71+
projectManager = new ProjectManager(rootPath, memfs, updater, true)
72+
await projectManager.ensureAllFiles().toPromise()
73+
})
9774
})
98-
})
99-
describe('getParentConfiguration()', () => {
100-
beforeEach(async () => {
101-
memfs = new InMemoryFileSystem('/')
102-
const localfs = new MapFileSystem(new Map([
103-
['file:///tsconfig.json', '{}'],
104-
['file:///src/jsconfig.json', '{}']
105-
]))
106-
const updater = new FileSystemUpdater(localfs, memfs)
107-
projectManager = new ProjectManager('/', memfs, updater, true)
108-
await projectManager.ensureAllFiles().toPromise()
75+
76+
describe('ensureReferencedFiles()', () => {
77+
beforeEach(() => {
78+
const rootPath = uri2path(rootUri)
79+
memfs = new InMemoryFileSystem(rootPath)
80+
const localfs = new MapFileSystem(new Map([
81+
[rootUri + 'package.json', '{"name": "package-name-1"}'],
82+
[rootUri + 'node_modules/somelib/index.js', '/// <reference path="./pathref.d.ts"/>\n/// <reference types="node"/>'],
83+
[rootUri + 'node_modules/somelib/pathref.d.ts', ''],
84+
[rootUri + 'node_modules/%40types/node/index.d.ts', ''],
85+
[rootUri + 'src/dummy.ts', 'import * as somelib from "somelib";']
86+
]))
87+
const updater = new FileSystemUpdater(localfs, memfs)
88+
projectManager = new ProjectManager(rootPath, memfs, updater, true)
89+
})
90+
it('should ensure content for imports and references is fetched', async () => {
91+
await projectManager.ensureReferencedFiles(rootUri + 'src/dummy.ts').toPromise()
92+
memfs.getContent(rootUri + 'node_modules/somelib/index.js')
93+
memfs.getContent(rootUri + 'node_modules/somelib/pathref.d.ts')
94+
memfs.getContent(rootUri + 'node_modules/%40types/node/index.d.ts')
95+
})
10996
})
110-
it('should resolve best configuration based on file name', () => {
111-
const config = projectManager.getParentConfiguration('file:///src/foo.ts')
112-
assert.isDefined(config)
113-
assert.equal('/tsconfig.json', config!.configFilePath)
97+
describe('getConfiguration()', () => {
98+
beforeEach(async () => {
99+
const rootPath = uri2path(rootUri)
100+
memfs = new InMemoryFileSystem(rootPath)
101+
const localfs = new MapFileSystem(new Map([
102+
[rootUri + 'tsconfig.json', '{}'],
103+
[rootUri + 'src/jsconfig.json', '{}']
104+
]))
105+
const updater = new FileSystemUpdater(localfs, memfs)
106+
projectManager = new ProjectManager(rootPath, memfs, updater, true)
107+
await projectManager.ensureAllFiles().toPromise()
108+
})
109+
it('should resolve best configuration based on file name', () => {
110+
const jsConfig = projectManager.getConfiguration(uri2path(rootUri + 'src/foo.js'))
111+
const tsConfig = projectManager.getConfiguration(uri2path(rootUri + 'src/foo.ts'))
112+
assert.equal(uri2path(rootUri + 'tsconfig.json'), tsConfig.configFilePath)
113+
assert.equal(uri2path(rootUri + 'src/jsconfig.json'), jsConfig.configFilePath)
114+
assert.equal(Array.from(projectManager.configurations()).length, 2)
115+
})
114116
})
115-
})
116-
describe('getChildConfigurations()', () => {
117-
beforeEach(async () => {
118-
memfs = new InMemoryFileSystem('/')
119-
const localfs = new MapFileSystem(new Map([
120-
['file:///tsconfig.json', '{}'],
121-
['file:///foo/bar/tsconfig.json', '{}'],
122-
['file:///foo/baz/tsconfig.json', '{}']
123-
]))
124-
const updater = new FileSystemUpdater(localfs, memfs)
125-
projectManager = new ProjectManager('/', memfs, updater, true)
126-
await projectManager.ensureAllFiles().toPromise()
117+
describe('getParentConfiguration()', () => {
118+
beforeEach(async () => {
119+
const rootPath = uri2path(rootUri)
120+
memfs = new InMemoryFileSystem(rootPath)
121+
const localfs = new MapFileSystem(new Map([
122+
[rootUri + 'tsconfig.json', '{}'],
123+
[rootUri + 'src/jsconfig.json', '{}']
124+
]))
125+
const updater = new FileSystemUpdater(localfs, memfs)
126+
projectManager = new ProjectManager(rootPath, memfs, updater, true)
127+
await projectManager.ensureAllFiles().toPromise()
128+
})
129+
it('should resolve best configuration based on file name', () => {
130+
const config = projectManager.getParentConfiguration(rootUri + 'src/foo.ts')
131+
assert.isDefined(config)
132+
assert.equal(uri2path(rootUri + 'tsconfig.json'), config!.configFilePath)
133+
assert.equal(Array.from(projectManager.configurations()).length, 2)
134+
})
127135
})
128-
it('should resolve best configuration based on file name', () => {
129-
const configs = Array.from(projectManager.getChildConfigurations('file:///foo')).map(config => config.configFilePath)
130-
assert.deepEqual(configs, [
131-
'/foo/bar/tsconfig.json',
132-
'/foo/baz/tsconfig.json'
133-
])
136+
describe('getChildConfigurations()', () => {
137+
beforeEach(async () => {
138+
const rootPath = uri2path(rootUri)
139+
memfs = new InMemoryFileSystem(rootPath)
140+
const localfs = new MapFileSystem(new Map([
141+
[rootUri + 'tsconfig.json', '{}'],
142+
[rootUri + 'foo/bar/tsconfig.json', '{}'],
143+
[rootUri + 'foo/baz/tsconfig.json', '{}']
144+
]))
145+
const updater = new FileSystemUpdater(localfs, memfs)
146+
projectManager = new ProjectManager(rootPath, memfs, updater, true)
147+
await projectManager.ensureAllFiles().toPromise()
148+
})
149+
it('should resolve best configuration based on file name', () => {
150+
const configs = Array.from(projectManager.getChildConfigurations(rootUri + 'foo')).map(config => config.configFilePath)
151+
assert.deepEqual(configs, [
152+
uri2path(rootUri + 'foo/bar/tsconfig.json'),
153+
uri2path(rootUri + 'foo/baz/tsconfig.json')
154+
])
155+
assert.equal(Array.from(projectManager.configurations()).length, 4)
156+
})
134157
})
135158
})
136-
})
159+
}

0 commit comments

Comments
 (0)