11import React from 'react' ;
22import MonacoEditor from 'react-monaco-editor' ;
3- import { editor , IKeyboardEvent } from 'monaco-editor' ;
43import * as monaco from 'monaco-editor' ;
4+ import { editor , IKeyboardEvent } from 'monaco-editor' ;
55import {
6- VimModeKeymap ,
76 createVimModeAdapter ,
8- StatusBarAdapter
7+ StatusBarAdapter ,
8+ VimModeKeymap
99} from '~/plugins/vim/editor' ;
10- import { attachCustomCommands } from './commands' ;
10+ import { attachCustomCommands } from './commands' ;
1111
1212import {
1313 Connect ,
1414 formatFileDispatcher ,
1515 newFileChangeAction ,
16- runFileDispatcher ,
16+ newMarkerAction ,
1717 newSnippetLoadDispatcher ,
18- newMarkerAction
18+ runFileDispatcher ,
1919} from '~/store' ;
20- import { Analyzer } from '~/services/analyzer' ;
21- import { LANGUAGE_GOLANG , stateToOptions } from './props' ;
20+ import { Analyzer } from '~/services/analyzer' ;
21+ import { LANGUAGE_GOLANG , stateToOptions } from './props' ;
22+ import { getTimeNowUsageMarkers } from './utils' ;
23+ import { RuntimeType } from "@services/config" ;
2224
2325const ANALYZE_DEBOUNCE_TIME = 500 ;
2426
@@ -29,8 +31,10 @@ interface CodeEditorState {
2931
3032@Connect ( s => ( {
3133 code : s . editor . code ,
34+ fileName : s . editor . fileName ,
3235 darkMode : s . settings . darkMode ,
3336 vimModeEnabled : s . settings . enableVimMode ,
37+ isServerEnvironment : RuntimeType . isServerRuntime ( s . settings . runtime ) ,
3438 loading : s . status ?. loading ,
3539 options : s . monaco ,
3640 vim : s . vim ,
@@ -102,7 +106,12 @@ export default class CodeEditor extends React.Component<any, CodeEditorState> {
102106 editorInstance . focus ( ) ;
103107 }
104108
105- componentDidUpdate ( prevProps ) {
109+ private isFileOrEnvironmentChanged ( prevProps ) {
110+ return ( prevProps . isServerEnvironment !== this . props . isServerEnvironment ) ||
111+ ( prevProps . fileName !== this . props . fileName ) ;
112+ }
113+
114+ private applyVimModeChanges ( prevProps ) {
106115 if ( prevProps ?. vimModeEnabled === this . props . vimModeEnabled ) {
107116 return
108117 }
@@ -117,34 +126,60 @@ export default class CodeEditor extends React.Component<any, CodeEditorState> {
117126 this . vimAdapter ?. dispose ( ) ;
118127 }
119128
129+ componentDidUpdate ( prevProps ) {
130+ if ( this . isFileOrEnvironmentChanged ( prevProps ) ) {
131+ // Update editor markers on file or environment changes;
132+ this . doAnalyze ( this . props . code ) ;
133+ }
134+
135+ this . applyVimModeChanges ( prevProps ) ;
136+ }
137+
120138 componentWillUnmount ( ) {
121139 this . analyzer ?. dispose ( ) ;
122140 this . vimAdapter ?. dispose ( ) ;
123141 }
124142
125143 onChange ( newValue : string , _ : editor . IModelContentChangedEvent ) {
126144 this . props . dispatch ( newFileChangeAction ( newValue ) ) ;
127-
128- if ( this . analyzer ) {
129- this . doAnalyze ( newValue ) ;
130- }
145+ this . doAnalyze ( newValue ) ;
131146 }
132147
133148 private doAnalyze ( code : string ) {
134149 if ( this . _previousTimeout ) {
135150 clearTimeout ( this . _previousTimeout ) ;
136151 }
137152
138- this . _previousTimeout = setTimeout ( ( ) => {
153+ this . _previousTimeout = setTimeout ( async ( ) => {
139154 this . _previousTimeout = null ;
140- this . analyzer ?. analyzeCode ( code ) . then ( ( { markers} ) => {
141- editor . setModelMarkers (
142- this . editorInstance ?. getModel ( ) as editor . ITextModel ,
143- this . editorInstance ?. getId ( ) as string ,
144- markers
145- ) ;
146- this . props . dispatch ( newMarkerAction ( markers ) )
147- } ) . catch ( err => console . error ( 'failed to perform code analysis: %s' , err ) ) ;
155+
156+ // Code analysis contains 2 steps that run on different conditions:
157+ // 1. Run Go worker if it's available and check for errors
158+ // 2. Add warnings to `time.Now` calls if code runs on server.
159+ const promises = [
160+ this . analyzer ?. getMarkers ( code ) ?? null ,
161+ this . props . isServerEnvironment ? (
162+ Promise . resolve ( getTimeNowUsageMarkers ( code , this . editorInstance ! ) )
163+ ) : null
164+ ] . filter ( p => ! ! p ) ;
165+
166+ const results = await Promise . allSettled ( promises ) ;
167+ const markers = results . flatMap ( r => {
168+ // Can't do in beautiful way due of TS strict checks.
169+ if ( r . status === 'rejected' ) {
170+ console . error ( r . reason ) ;
171+ return [ ] ;
172+ }
173+
174+ return r . value ?? [ ] ;
175+ } ) ;
176+
177+ editor . setModelMarkers (
178+ this . editorInstance ?. getModel ( ) as editor . ITextModel ,
179+ this . editorInstance ?. getId ( ) as string ,
180+ markers
181+ ) ;
182+ this . props . dispatch ( newMarkerAction ( markers ) ) ;
148183 } , ANALYZE_DEBOUNCE_TIME ) ;
149184 }
150185
0 commit comments