Skip to content

Commit 49a08d9

Browse files
authored
Merge pull request #863 from c-git/main_detection_update
Add detection of main under more circumstances
2 parents 167a389 + 39186ac commit 49a08d9

File tree

4 files changed

+35
-19
lines changed

4 files changed

+35
-19
lines changed

ui/frontend/.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ module.exports = {
9797
'reducers/selection.ts',
9898
'reducers/versions.ts',
9999
'reducers/websocket.ts',
100+
'selectors/index.spec.ts',
100101
'types.ts',
101102
'websocketActions.ts',
102103
'websocketMiddleware.ts',

ui/frontend/.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ node_modules
4848
!reducers/selection.ts
4949
!reducers/versions.ts
5050
!reducers/websocket.ts
51+
!selectors/index.spec.ts
5152
!types.ts
5253
!websocketActions.ts
5354
!websocketMiddleware.ts

ui/frontend/selectors/index.spec.ts

+24-18
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,66 @@
11
import reducer from '../reducers';
22
import { editCode } from '../reducers/code';
3-
43
import { hasMainFunctionSelector } from './index';
54

6-
const buildState = (code: string) => {
7-
const state = reducer(undefined, editCode(code));
8-
return state;
9-
};
5+
const buildState = (code: string) => reducer(undefined, editCode(code));
6+
7+
const doMainFunctionSelector = (code: string) => hasMainFunctionSelector(buildState(code));
108

119
describe('checking for a main function', () => {
1210
test('empty code has no main', () => {
13-
expect(hasMainFunctionSelector(buildState(''))).toBe(false);
11+
expect(doMainFunctionSelector('')).toBe(false);
1412
});
1513

1614
test('a plain main counts', () => {
17-
expect(hasMainFunctionSelector(buildState('fn main()'))).toBe(true);
15+
expect(doMainFunctionSelector('fn main()')).toBe(true);
1816
});
1917

2018
test('a public main counts', () => {
21-
expect(hasMainFunctionSelector(buildState('pub fn main()'))).toBe(true);
19+
expect(doMainFunctionSelector('pub fn main()')).toBe(true);
2220
});
2321

2422
test('an async main counts', () => {
25-
expect(hasMainFunctionSelector(buildState('async fn main()'))).toBe(true);
23+
expect(doMainFunctionSelector('async fn main()')).toBe(true);
2624
});
2725

2826
test('a public async main counts', () => {
29-
expect(hasMainFunctionSelector(buildState('pub async fn main()'))).toBe(true);
27+
expect(doMainFunctionSelector('pub async fn main()')).toBe(true);
3028
});
3129

3230
test('a const main counts', () => {
33-
expect(hasMainFunctionSelector(buildState('const fn main()'))).toBe(true);
31+
expect(doMainFunctionSelector('const fn main()')).toBe(true);
3432
});
3533

3634
test('a public const main counts', () => {
37-
expect(hasMainFunctionSelector(buildState('pub const fn main()'))).toBe(true);
35+
expect(doMainFunctionSelector('pub const fn main()')).toBe(true);
3836
});
3937

4038
test('a public const async main counts', () => {
41-
expect(hasMainFunctionSelector(buildState('pub const async fn main()'))).toBe(true);
39+
expect(doMainFunctionSelector('pub const async fn main()')).toBe(true);
4240
});
4341

4442
test('leading indentation is ignored', () => {
45-
expect(hasMainFunctionSelector(buildState('\t fn main()'))).toBe(true);
43+
expect(doMainFunctionSelector('\t fn main()')).toBe(true);
4644
});
4745

4846
test('extra space everywhere is ignored', () => {
49-
expect(hasMainFunctionSelector(buildState(' pub async fn main ( )'))).toBe(true);
47+
expect(doMainFunctionSelector(' pub async fn main ( )')).toBe(true);
5048
});
5149

5250
test('a commented-out main does not count', () => {
53-
expect(hasMainFunctionSelector(buildState('// fn main()'))).toBe(false);
54-
expect(hasMainFunctionSelector(buildState('/* fn main()'))).toBe(false);
51+
expect(doMainFunctionSelector('// fn main()')).toBe(false);
52+
expect(doMainFunctionSelector('/* fn main()')).toBe(false);
5553
});
5654

5755
test('a function with the substring main does not count', () => {
58-
expect(hasMainFunctionSelector(buildState('fn mainly()'))).toBe(false);
56+
expect(doMainFunctionSelector('fn mainly()')).toBe(false);
57+
});
58+
59+
test('a main function after other items on the same line', () => {
60+
expect(doMainFunctionSelector('use std; fn main(){ println!("Hello, world!"); }')).toBe(true);
61+
});
62+
63+
test('a main function with a block comment in the argument list', () => {
64+
expect(doMainFunctionSelector('fn main(/* comment */) {')).toBe(true);
5965
});
6066
});

ui/frontend/selectors/index.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,15 @@ export const selectionSelector = (state: State) => state.selection;
2020
const HAS_TESTS_RE = /^\s*#\s*\[\s*test\s*([^"]*)]/m;
2121
export const hasTestsSelector = createSelector(codeSelector, code => !!code.match(HAS_TESTS_RE));
2222

23-
const HAS_MAIN_FUNCTION_RE = /^\s*(pub\s+)?\s*(const\s+)?\s*(async\s+)?\s*fn\s+main\s*\(\s*\)/m;
23+
// https://stackoverflow.com/a/34755045/155423
24+
const HAS_MAIN_FUNCTION_RE = new RegExp(
25+
[
26+
/^([^\n\r\/]*;)?/,
27+
/\s*(pub\s+)?\s*(const\s+)?\s*(async\s+)?\s*/,
28+
/fn\s+main\s*\(\s*(\/\*.*\*\/)?\s*\)/,
29+
].map((r) => r.source).join(''),
30+
'm'
31+
);
2432
export const hasMainFunctionSelector = createSelector(codeSelector, code => !!code.match(HAS_MAIN_FUNCTION_RE));
2533

2634
const CRATE_TYPE_RE = /^\s*#!\s*\[\s*crate_type\s*=\s*"([^"]*)"\s*]/m;

0 commit comments

Comments
 (0)