Skip to content

Commit fe01b27

Browse files
authored
Merge pull request #3 from atom-community/fixes
2 parents 2086cd9 + 933b58f commit fe01b27

File tree

9 files changed

+111
-92
lines changed

9 files changed

+111
-92
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"test": "npm run build.unit && npm run test.only",
1414
"test.only": "atom --test ./dist/spec",
1515
"clean": "shx rm -rf dist",
16-
"build.unit": "tsc -p ./tsconfig.json || echo done",
16+
"build.unit": "tsc -p ./tsconfig.json",
1717
"dev": "npm run clean && cross-env NODE_ENV=development cross-env BABEL_KEEP_MODULES=true rollup -c -w",
1818
"build": "npm run clean && cross-env NODE_ENV=production cross-env BABEL_KEEP_MODULES=true rollup -c ",
1919
"build-commit": "build-commit -o dist",
@@ -82,7 +82,7 @@
8282
"shx": "^0.3.3",
8383
"temp": "^0.9.4",
8484
"typescript": "^4.3.5",
85-
"waitsfor": "^0.0.6"
85+
"waitit": "^1.0.3"
8686
},
8787
"prettier": "prettier-config-atomic"
8888
}

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rollup.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const RollupConfig = [
1313
},
1414
],
1515
// loaded externally
16-
external: ["atom", "log4js", "rxjs-compat"],
16+
external: ["atom", "log4js", "rxjs-compat/bundles/rxjs-compat.umd.min.js"],
1717
plugins,
1818
},
1919
]

spec/CodeFormatManager-spec.ts

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
1-
import { Range } from "atom"
1+
import { Range, TextEditor } from "atom"
22
import { observeTextEditors } from "@atom-ide-community/nuclide-commons-atom/FileEventHandlers"
33
import CodeFormatManager, { SAVE_TIMEOUT } from "../src/CodeFormatManager"
44
import UniversalDisposable from "@atom-ide-community/nuclide-commons/UniversalDisposable"
55
import temp from "temp"
66
import * as config from "../src/config"
7-
import { waitsFor } from "waitsfor"
8-
9-
const sleep = (n) => new Promise((r) => setTimeout(r, n))
7+
import { waitFor, sleep } from "./utils"
108

119
jasmine.DEFAULT_TIMEOUT_INTERVAL = SAVE_TIMEOUT + 100
1210
describe("CodeFormatManager", () => {
13-
let textEditor
14-
let manager
15-
let disposables
11+
let textEditor: TextEditor
12+
let manager: CodeFormatManager
13+
let disposables: UniversalDisposable
1614
beforeEach(async () => {
1715
manager = new CodeFormatManager()
1816
disposables = new UniversalDisposable(observeTextEditors())
1917
temp.track()
2018
const file = temp.openSync()
2119
textEditor = await atom.workspace.open(file.path)
2220
})
23-
afterEach(async () => {
21+
afterEach(() => {
2422
manager.dispose()
2523
disposables.dispose()
2624
})
@@ -38,10 +36,8 @@ describe("CodeFormatManager", () => {
3836
]),
3937
})
4038
textEditor.setText("abc")
41-
atom.commands.dispatch(atom.views.getView(textEditor), "code-format:format-code")
42-
await waitsFor(() => textEditor.getText() === "def", {
43-
timeout: SAVE_TIMEOUT,
44-
})
39+
await atom.commands.dispatch(atom.views.getView(textEditor), "code-format:format-code")
40+
await waitFor(() => textEditor.getText() === "def")
4541
})
4642
it("format an editor using formatEntireFile", async () => {
4743
manager.addFileProvider({
@@ -53,10 +49,8 @@ describe("CodeFormatManager", () => {
5349
}),
5450
})
5551
textEditor.setText("abc")
56-
atom.commands.dispatch(atom.views.getView(textEditor), "code-format:format-code")
57-
await waitsFor(() => textEditor.getText() === "ghi", {
58-
timeout: SAVE_TIMEOUT,
59-
})
52+
await atom.commands.dispatch(atom.views.getView(textEditor), "code-format:format-code")
53+
await waitFor(() => textEditor.getText() === "ghi")
6054
})
6155
it("formats an editor on type", async () => {
6256
spyOn(config, "getFormatOnType").and.returnValue(true)
@@ -79,11 +73,9 @@ describe("CodeFormatManager", () => {
7973
textEditor.setCursorBufferPosition([0, 1])
8074
textEditor.insertText("b")
8175
textEditor.insertText("c")
82-
await waitsFor(() => textEditor.getText() === "def", {
83-
timeout: SAVE_TIMEOUT,
84-
})
76+
await waitFor(() => textEditor.getText() === "def")
8577
// Debouncing should ensure only one format call.
86-
expect(spy.mock.calls.length).toBe(1)
78+
expect(spy.calls.count()).toBe(1)
8779
})
8880
it("formats an editor on save", async () => {
8981
spyOn(config, "getFormatOnSave").and.returnValue(true)
@@ -114,12 +106,11 @@ describe("CodeFormatManager", () => {
114106
},
115107
})
116108
const spy = spyOn(textEditor.getBuffer(), "save")
109+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
117110
textEditor.save()
118111
// Wait until the buffer has been saved and verify it has been saved exactly
119112
// once.
120-
await waitsFor(() => spy.mock.calls.length > 0, {
121-
timeout: SAVE_TIMEOUT,
122-
})
123-
expect(spy.mock.calls.length).toBe(1)
113+
await waitFor(() => spy.calls.count() > 0)
114+
expect(spy.calls.count()).toBe(1)
124115
})
125116
})

spec/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as waitit from "waitit"
2+
3+
/** Wait until a function returns true */
4+
export function waitFor(fn: (...args: any[]) => boolean, timeout = 2500) {
5+
const interval = 100 // check very 100 ms
6+
return waitit.start({
7+
interval,
8+
maxTicks: timeout / interval,
9+
check: fn,
10+
})
11+
}
12+
13+
/** Sleep for ms */
14+
export function sleep(ms) {
15+
return new Promise((resolve) => setTimeout(resolve, ms))
16+
}

src/CodeFormatManager.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Point, TextEditor, TextChange, Disposable } from "atom"
1+
import type { TextEditor, TextChange, Disposable } from "atom"
22
// TODO add to @types/atom
33
type AggregatedTextChange = {
44
changes: Array<TextChange>
@@ -78,7 +78,7 @@ export default class CodeFormatManager {
7878

7979
// Events from editor actions (saving, typing).
8080
const editorEvents = observableFromSubscribeFunction((cb) => atom.workspace.observeTextEditors(cb)).mergeMap(
81-
(editor) => this._getEditorEventStream(editor)
81+
(editor) => _getEditorEventStream(editor)
8282
)
8383

8484
return (
@@ -97,22 +97,6 @@ export default class CodeFormatManager {
9797
)
9898
}
9999

100-
/** Returns a stream of all typing and saving operations from the editor. */
101-
_getEditorEventStream(editor: TextEditor): Observable<FormatEvent> {
102-
const changeEvents = observableFromSubscribeFunction((callback) => editor.getBuffer().onDidChangeText(callback))
103-
104-
// We need to capture when editors are about to be destroyed in order to
105-
// interrupt any pending formatting operations. (Otherwise, we may end up
106-
// attempting to save a destroyed editor!)
107-
const willDestroyEvents = observableFromSubscribeFunction((cb) => atom.workspace.onWillDestroyPaneItem(cb)).filter(
108-
(event) => event.item === editor
109-
)
110-
111-
return Observable.merge(changeEvents.map((edit) => ({ type: "type", editor, edit }))).takeUntil(
112-
Observable.merge(observeEditorDestroy(editor), willDestroyEvents)
113-
)
114-
}
115-
116100
_handleEvent(event: FormatEvent): Observable<unknown> {
117101
const { editor } = event
118102
switch (event.type) {
@@ -142,14 +126,6 @@ export default class CodeFormatManager {
142126
}
143127
}
144128

145-
// Checks whether contents are same in the buffer post-format, throwing if
146-
// anything has changed.
147-
_checkContentsAreSame(before: string, after: string): void {
148-
if (before !== after) {
149-
throw new Error("The file contents were changed before formatting was complete.")
150-
}
151-
}
152-
153129
// Return the text edits used to format code in the editor specified.
154130
_formatCodeInTextEditor(editor: TextEditor, range?: Range): Observable<Array<TextEdit>> {
155131
return Observable.defer(() => {
@@ -197,7 +173,7 @@ export default class CodeFormatManager {
197173
return Observable.of(firstNonNull)
198174
}
199175
})
200-
.map(({ _, formatted }) => {
176+
.map(({ formatted }) => {
201177
return [
202178
{
203179
oldRange: editor.getBuffer().getRange(),
@@ -270,7 +246,7 @@ export default class CodeFormatManager {
270246
if (edits.length === 0) {
271247
return
272248
}
273-
this._checkContentsAreSame(contents, editor.getText())
249+
_checkContentsAreSame(contents, editor.getText())
274250
// Note that this modification is not in a transaction, so it applies as a
275251
// separate editing event than the character typing. This means that you
276252
// can undo just the formatting by attempting to undo once, and then undo
@@ -394,5 +370,29 @@ function isBracketPair(typedText: string): boolean {
394370
return false
395371
}
396372
const validBracketPairs: Array<string> = atom.config.get("bracket-matcher.autocompleteCharacters") as any
397-
return validBracketPairs.indexOf(typedText) !== -1
373+
return validBracketPairs.includes(typedText)
374+
}
375+
376+
// Checks whether contents are same in the buffer post-format, throwing if
377+
// anything has changed.
378+
function _checkContentsAreSame(before: string, after: string): void {
379+
if (before !== after) {
380+
throw new Error("The file contents were changed before formatting was complete.")
381+
}
382+
}
383+
384+
/** Returns a stream of all typing and saving operations from the editor. */
385+
function _getEditorEventStream(editor: TextEditor): Observable<FormatEvent> {
386+
const changeEvents = observableFromSubscribeFunction((callback) => editor.getBuffer().onDidChangeText(callback))
387+
388+
// We need to capture when editors are about to be destroyed in order to
389+
// interrupt any pending formatting operations. (Otherwise, we may end up
390+
// attempting to save a destroyed editor!)
391+
const willDestroyEvents = observableFromSubscribeFunction((cb) => atom.workspace.onWillDestroyPaneItem(cb)).filter(
392+
(event) => event.item === editor
393+
)
394+
395+
return Observable.merge(changeEvents.map((edit) => ({ type: "type", editor, edit }))).takeUntil(
396+
Observable.merge(observeEditorDestroy(editor), willDestroyEvents)
397+
)
398398
}

src/legacy-provider.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// TODO Remove
2+
3+
import type { Disposable } from "atom"
4+
import { consumeRangeProvider, consumeFileProvider, consumeOnSaveProvider, consumeOnTypeProvider } from "./main"
5+
import type { CodeFormatProvider } from "./types"
6+
7+
export function consumeLegacyProvider(provider: CodeFormatProvider): Disposable {
8+
// Legacy providers used `selector` / `inclusionPriority`.
9+
// @ts-ignore legacy API compatability.
10+
provider.grammarScopes =
11+
provider.grammarScopes ||
12+
// @ts-ignore
13+
(provider.selector != null ? provider.selector.split(", ") : null)
14+
provider.priority =
15+
provider.priority != null
16+
? provider.priority
17+
: // @ts-ignore
18+
provider.inclusionPriority != null
19+
? // @ts-ignore
20+
provider.inclusionPriority
21+
: 0
22+
if ("formatCode" in provider) {
23+
return consumeRangeProvider(provider)
24+
} else if ("formatEntireFile" in provider) {
25+
return consumeFileProvider(provider)
26+
} else if ("formatAtPosition" in provider) {
27+
return consumeOnTypeProvider(provider)
28+
} else if ("formatOnSave" in provider) {
29+
return consumeOnSaveProvider(provider)
30+
}
31+
throw new Error("Invalid code format provider")
32+
}

src/main.ts

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { Disposable } from "atom"
22
import type { BusySignalService } from "atom-ide-base"
33
import type {
4-
CodeFormatProvider,
54
RangeCodeFormatProvider,
65
FileCodeFormatProvider,
76
OnTypeCodeFormatProvider,
@@ -18,32 +17,6 @@ export function activate() {
1817
codeFormatManager = new CodeFormatManager()
1918
}
2019

21-
export function consumeLegacyProvider(provider: CodeFormatProvider): Disposable {
22-
// Legacy providers used `selector` / `inclusionPriority`.
23-
// $FlowIgnore legacy API compatability.
24-
provider.grammarScopes =
25-
provider.grammarScopes ||
26-
// $FlowIgnore
27-
(provider.selector != null ? provider.selector.split(", ") : null)
28-
provider.priority =
29-
provider.priority != null
30-
? provider.priority
31-
: // $FlowFixMe(>=0.68.0) Flow suppress (T27187857)
32-
provider.inclusionPriority != null
33-
? provider.inclusionPriority
34-
: 0
35-
if (provider.formatCode) {
36-
return consumeRangeProvider(provider)
37-
} else if (provider.formatEntireFile) {
38-
return consumeFileProvider(provider)
39-
} else if (provider.formatAtPosition) {
40-
return consumeOnTypeProvider(provider)
41-
} else if (provider.formatOnSave) {
42-
return consumeOnSaveProvider(provider)
43-
}
44-
throw new Error("Invalid code format provider")
45-
}
46-
4720
export function consumeRangeProvider(provider: RangeCodeFormatProvider): Disposable {
4821
return codeFormatManager.addRangeProvider(provider)
4922
}
@@ -67,3 +40,6 @@ export function consumeBusySignal(busySignalService: BusySignalService): Disposa
6740
export function deactivate() {
6841
codeFormatManager.dispose()
6942
}
43+
44+
// TODO remove
45+
export { consumeLegacyProvider } from "./legacy-provider"

tsconfig.json

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"compilerOptions": {
3-
"strict": false,
4-
"strictNullChecks": false,
5-
"noUnusedLocals": false,
6-
"noUnusedParameters": false,
7-
"noImplicitReturns": false,
3+
"strict": true,
4+
"strictNullChecks": true,
5+
"noUnusedLocals": true,
6+
"noUnusedParameters": true,
7+
"noImplicitReturns": true,
88
"noImplicitAny": false,
9-
"noImplicitThis": false,
10-
"noFallthroughCasesInSwitch": false,
9+
"noImplicitThis": true,
10+
"noFallthroughCasesInSwitch": true,
1111
"declaration": true,
1212
"emitDecoratorMetadata": true,
1313
"experimentalDecorators": true,
@@ -17,8 +17,6 @@
1717
"preserveSymlinks": true,
1818
"removeComments": false,
1919
"isolatedModules": true,
20-
"jsx": "preserve",
21-
"jsxImportSource": "solid-js",
2220
"downlevelIteration": true,
2321
"lib": ["ES2019", "dom"],
2422
"target": "ES2018",

0 commit comments

Comments
 (0)