11import type { ParseError } from 'dt-sql-parser' ;
2+ import { ColumnEntityContext , CommonEntityContext , EntityContextType } from 'dt-sql-parser' ;
23import { EntityContext } from 'dt-sql-parser/dist/parser/common/entityCollector' ;
34import { WordPosition } from 'dt-sql-parser/dist/parser/common/textAndWord' ;
45import * as monaco from 'monaco-editor' ;
@@ -17,6 +18,16 @@ import {
1718} from './fillers/monaco-editor-core' ;
1819import type { CompletionSnippet , LanguageServiceDefaults } from './monaco.contribution' ;
1920
21+ export interface ColumnInfo {
22+ /** 字段名 */
23+ column : string ;
24+ /** 字段类型 */
25+ type : string | undefined ;
26+ /** 注释 */
27+ comment ?: string ;
28+ /** 别名 */
29+ alias ?: string ;
30+ }
2031export interface WorkerAccessor < T extends BaseSQLWorker > {
2132 ( ...uris : Uri [ ] ) : Promise < T > ;
2233}
@@ -352,3 +363,105 @@ export class ReferenceAdapter<T extends BaseSQLWorker> implements languages.Refe
352363 } ) ;
353364 }
354365}
366+ /**
367+ * The adapter is for the hover provider interface defines the contract between extensions and
368+ * the [hover](https://code.visualstudio.com/docs/editor/intellisense)-feature.
369+ **/
370+ export class HoverAdapter < T extends BaseSQLWorker > implements languages . HoverProvider {
371+ constructor (
372+ private readonly _worker : WorkerAccessor < T > ,
373+ private readonly _defaults : LanguageServiceDefaults
374+ ) { }
375+ provideHover (
376+ model : editor . IReadOnlyModel ,
377+ position : Position ,
378+ _token : CancellationToken
379+ ) : languages . ProviderResult < languages . Hover > {
380+ const resource = model . uri ;
381+ const lineContent = model . getLineContent ( position . lineNumber ) ;
382+ if ( lineContent . trim ( ) . startsWith ( '--' ) ) return null ;
383+ return this . _worker ( resource )
384+ . then ( ( worker ) => {
385+ let code = model ?. getValue ( ) || '' ;
386+ if ( typeof this . _defaults . preprocessCode === 'function' ) {
387+ code = this . _defaults . preprocessCode ( code ) ;
388+ }
389+ return worker . getAllEntities ( code , position ) ;
390+ } )
391+ . then ( ( entities ) => {
392+ if ( ! entities || ! entities . length ) return null ;
393+ const curEntity = entities . find ( ( entity : EntityContext ) => {
394+ const p = entity . position ;
395+ return (
396+ p . startColumn <= position . column &&
397+ p . endColumn >= position . column &&
398+ p . line === position . lineNumber
399+ ) ;
400+ } ) ;
401+ if ( ! curEntity ) return null ;
402+ const tableCreate = curEntity ? findTableCreateEntity ( curEntity , entities ) : null ;
403+ const columns = tableCreate ? toColumnsInfo ( tableCreate ) || [ ] : [ ] ;
404+ const columnsDesc = columns . reduce ( ( res , cur ) => {
405+ const { column, type, comment, alias } = cur ;
406+ return (
407+ res +
408+ `\`${ column } \` ${ type ? ` **${ type } **` : '' } ${
409+ comment ? ` *${ comment } *` : ''
410+ } ${ alias ? ` *${ alias } *` : '' } \n`
411+ ) ;
412+ } , '' ) ;
413+ const pos = curEntity . position ;
414+ const range = new monaco . Range ( pos . line , pos . startColumn , pos . line , pos . endColumn ) ;
415+ const contents : monaco . IMarkdownString [ ] = [
416+ { value : `**${ curEntity . text } **` } ,
417+ { value : columnsDesc }
418+ ] ;
419+ return { contents, range } ;
420+ } ) ;
421+ }
422+ }
423+
424+ export function isTableCreateEntity ( en : EntityContext ) : en is CommonEntityContext {
425+ return en . entityContextType === EntityContextType . TABLE_CREATE ;
426+ }
427+ /**
428+ * According to the table name or table entity field, get the corresponding create table information
429+ */
430+ export function findTableCreateEntity (
431+ tableEntity : EntityContext | string ,
432+ allEntities : EntityContext [ ]
433+ ) : CommonEntityContext | null {
434+ if (
435+ typeof tableEntity !== 'string' &&
436+ tableEntity . entityContextType !== EntityContextType . TABLE
437+ ) {
438+ return null ;
439+ }
440+
441+ const tableName : string = typeof tableEntity === 'string' ? tableEntity : tableEntity . text ;
442+ return (
443+ allEntities . find (
444+ ( en ) : en is CommonEntityContext =>
445+ en . entityContextType === EntityContextType . TABLE_CREATE && en . text === tableName
446+ ) ?? null
447+ ) ;
448+ }
449+
450+ /**
451+ * Transform table create entity to columns info
452+ */
453+ export function toColumnsInfo ( tableEntity : CommonEntityContext ) : ColumnInfo [ ] | null {
454+ if ( ! tableEntity ) return null ;
455+ if ( tableEntity . entityContextType !== EntityContextType . TABLE_CREATE ) return null ;
456+ if ( ! tableEntity . columns ?. length ) return null ;
457+ const columnsInfo : ColumnInfo [ ] = [ ] ;
458+ tableEntity . columns . forEach ( ( col : ColumnEntityContext ) => {
459+ columnsInfo . push ( {
460+ column : col . text ,
461+ type : col . _colType ?. text ,
462+ comment : col . _comment ?. text ,
463+ alias : col . _alias ?. text
464+ } ) ;
465+ } ) ;
466+ return columnsInfo ;
467+ }
0 commit comments