2019-09-29 10:48:37 +00:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2019-09-27 10:47:42 +00:00
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
2019-09-29 10:48:37 +00:00
2019-09-27 10:47:42 +00:00
import * as vscode from 'vscode' ;
2019-10-12 10:29:34 +00:00
import { Provider } from './codeAction' ;
2019-09-27 10:47:42 +00:00
2019-09-29 10:48:37 +00:00
class StructInfo {
2019-09-30 10:38:01 +00:00
ShorthandName : string ;
2019-09-29 10:48:37 +00:00
Name : string ;
Range : number [ ] ;
2019-09-30 10:38:01 +00:00
Fields : Map < string , Field > ;
2019-09-29 10:48:37 +00:00
constructor ( name : string , fields : Field [ ] , range : number [ ] ) {
this . Name = name ;
2019-09-30 10:38:01 +00:00
var sname : string = "" ;
sname += this . Name [ 0 ] . toLowerCase ( ) ;
for ( let i = 1 ; i < this . Name . length ; i ++ ) {
let c = this . Name . charCodeAt ( i ) ;
if ( c <= 90 && c >= 65 ) {
sname += this . Name [ i ] . toLowerCase ( ) ;
}
}
this . ShorthandName = this . Name ;
2019-09-29 10:48:37 +00:00
this . Range = range ;
2019-09-30 10:38:01 +00:00
this . Fields = new Map < string , Field > ( ) ;
2019-10-08 10:22:24 +00:00
fields . forEach ( ( value ) = > {
2019-09-30 10:38:01 +00:00
this . Fields . set ( value . Key , value ) ;
} ) ;
2019-09-29 10:48:37 +00:00
}
getFieldsString ( ) : string [ ] {
var result : string [ ] = [ ] ;
2019-09-30 10:38:01 +00:00
this . Fields . forEach ( ( field , index ) = > {
result . push ( this . Name + field . toString ( ) ) ;
2019-09-29 10:48:37 +00:00
} ) ;
return result ;
}
}
class Field {
Parent : string ;
Type : string ;
Name : string ;
Range : number [ ] ;
2019-09-30 10:38:01 +00:00
Key : string ;
2019-09-29 10:48:37 +00:00
constructor ( parent : string , type : string , name : string , range : number [ ] ) {
this . Parent = parent ;
this . Type = type ;
this . Name = name ;
this . Range = range ;
2019-10-08 10:22:24 +00:00
this . Key = ( this . Parent . substr ( 1 ) + this . Name [ 0 ] . toUpperCase ( ) + this . Name . substr ( 1 ) ) . replace ( new RegExp ( "\\." , "g" ) , "" ) ;
// TODO: 大小写Map的问题
2019-09-30 10:38:01 +00:00
}
toString ( ) : string {
return this . Parent . substr ( 1 ) + this . Name + " " + this . Type ;
2019-09-29 10:48:37 +00:00
}
}
2019-09-27 10:47:42 +00:00
2019-10-12 10:29:34 +00:00
let typeMap = new Map < string , GeneratorType > ( ) ;
let typeCharMap = new Map < GeneratorType , string > ( ) ;
2019-09-27 10:47:42 +00:00
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
2019-09-29 10:48:37 +00:00
function activate ( context : vscode.ExtensionContext ) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console . log ( 'Congratulations, your extension "go-quickly-generator" is now active!' ) ;
2019-10-08 10:22:24 +00:00
2019-10-12 10:29:34 +00:00
typeMap . set ( "Getter" , GeneratorType . Getter ) ;
typeMap . set ( "Setter" , GeneratorType . Setter ) ;
typeCharMap . set ( GeneratorType . Getter , "G" ) ;
typeCharMap . set ( GeneratorType . Setter , "S" ) ;
typeCharMap . set ( GeneratorType . Getter | GeneratorType . Setter , "GS" ) ;
2019-10-08 10:22:24 +00:00
context . subscriptions . push ( vscode . commands . registerCommand ( 'Go-Quickly-Generator.Go-Gen-GetSet' , ( ) = > {
2019-09-29 10:48:37 +00:00
// The code you place here will be executed every time your command is executed
// Display a message box to the user
let sinfo = GetStruct ( ) ;
2019-10-08 10:22:24 +00:00
if ( sinfo ) {
2019-10-12 10:29:34 +00:00
vscode . window . showQuickPick ( [ "Getter" , "Setter" ] , < vscode.QuickPickOptions > { canPickMany : true , placeHolder : "select generator type getter or setter" } ) . then ( items = > {
console . log ( items ) ;
let myitems = items as any as string [ ] ;
let t = GeneratorType . Unknown ;
myitems . forEach ( ( value ) = > {
let sel = typeMap . get ( value ) ;
if ( sel ) {
t = t | sel ;
}
} ) ;
if ( sinfo ) {
GeneratorSetGet ( sinfo , t ) ;
}
} ) ;
// GeneratorSetGet(sinfo, GeneratorType.Getter | GeneratorType.Setter);
2019-10-08 10:22:24 +00:00
} else {
vscode . window . showErrorMessage ( "there is no struct(go) to focus. you can move point to struct(go)" ) ;
2019-09-29 10:48:37 +00:00
}
} ) ) ;
2019-10-12 10:29:34 +00:00
// context.subscriptions.push(vscode.languages.registerCodeActionsProvider(
// "go", new Provider(), { providedCodeActionKinds: [vscode.CodeActionKind.Source] }
// ));
2019-09-29 10:48:37 +00:00
2019-10-12 10:29:34 +00:00
context . subscriptions . push ( vscode . commands . registerCommand ( 'Go-Quickly-Generator.Getter' , function ( ) {
2019-09-29 10:48:37 +00:00
let editor = vscode . window . activeTextEditor ;
if ( editor !== undefined ) {
const currentPos = editor . selection . active ;
const lineCount = editor . document . lineCount ;
// let selection = editor.selection;
// let lineText = editor.document.lineAt(selection.active);
// vscode.window.showInformationMessage( lineText.text );
}
} ) ) ;
2019-09-27 10:47:42 +00:00
}
2019-10-08 10:22:24 +00:00
function getAbbreviation ( name : string ) : string | undefined {
if ( name . length ) {
let shortName = name [ 0 ] . toLowerCase ( ) ;
let m = name . substr ( 1 ) . match ( "[A-Z]" ) ;
if ( m ) {
m . forEach ( ( v ) = > {
shortName += v . toLowerCase ( ) ;
} ) ;
return shortName ;
}
}
return undefined ;
}
2019-10-12 10:29:34 +00:00
enum GeneratorType {
Unknown = 0 ,
Setter = 1 << 0 ,
Getter = 1 << 1 ,
}
function GeneratorSetGet ( sinfo : StructInfo , stype : GeneratorType ) {
2019-10-08 10:22:24 +00:00
console . log ( sinfo ) ;
let editor = vscode . window . activeTextEditor ;
if ( editor !== undefined ) {
2019-10-12 10:29:34 +00:00
let gtypechar = typeCharMap . get ( stype ) as string ;
let regexFunction = ` ^func {0,} \\ (.+ ${ sinfo . Name } {0,} \\ ) {0,}[ ${ gtypechar } ]et([a-zA-Z_]+) {0,} \\ ( ` ;
2019-10-08 10:22:24 +00:00
// console.log(regexFunction);
let existsStructFunctions : Set < string > = new Set < string > ( ) ;
for ( let n = 0 ; n < editor . document . lineCount ; n ++ ) {
let line = editor . document . lineAt ( n ) ;
let matches = line . text . match ( regexFunction ) ;
if ( matches !== null ) {
existsStructFunctions . add ( matches [ 1 ] ) ;
}
}
const options = < vscode.QuickPickOptions > { canPickMany : true , placeHolder : "select the fields that would be generator get set" } ;
var items : vscode.QuickPickItem [ ] = [ ] ;
var obj = {
info : sinfo ,
exists : existsStructFunctions ,
items : function ( ) {
this . info . Fields . forEach ( ( value , key ) = > {
if ( this . exists . has ( key ) ) {
vscode . window . showInformationMessage ( "Get" + key + " or Set" + key + " is Exists" ) ;
} else {
items . push ( < vscode.QuickPickItem > {
label : value.toString ( ) ,
detail : this.info.Name ,
description : key ,
} ) ;
}
} ) ;
} ,
pick : function ( ) {
this . items ( ) ;
vscode . window . showQuickPick ( items , options ) . then ( ( item ) = > {
if ( item ) {
let fields = item as any as vscode . QuickPickItem [ ] ;
let sname = getAbbreviation ( this . info . Name ) as string ;
let structString = ` func ( ${ sname } * ${ this . info . Name } ) ` ;
fields . forEach ( ( qitem ) = > {
let field = this . info . Fields . get ( qitem . description as string ) ;
if ( field ) {
let editor = vscode . window . activeTextEditor ;
if ( editor ) {
let keyName = field . Name [ 0 ] . toUpperCase ( ) + field . Name . substr ( 1 ) ;
let funcitonName = field . Parent . replace ( new RegExp ( "\\." , "g" ) , "" ) + keyName ;
// Set
2019-10-12 10:29:34 +00:00
if ( stype & GeneratorType . Setter ) {
let prefix = "Set" ;
let setFunction = prefix + funcitonName ;
let params = ` ( ${ field . Name } ${ field . Type } ) ` ;
let comment = ` // ${ setFunction } ${ prefix } ${ field . Name } ${ field . Type } \ n ` ;
let ss = new vscode . SnippetString ( ` \ n ${ comment } ${ structString } ${ setFunction } ${ params } { \ n \ t ${ sname } ${ field . Parent } ${ field . Name } = ${ field . Name } \ n} \ n ` ) ;
editor . insertSnippet ( ss , new vscode . Position ( this . info . Range [ 1 ] + 1 , 0 ) ) ;
}
if ( stype & GeneratorType . Getter ) {
let prefix = "Get" ;
let getFunction = prefix + funcitonName ;
let comment = ` // ${ getFunction } ${ prefix } return ${ field . Name } ${ field . Type } \ n ` ;
let ss = new vscode . SnippetString ( ` \ n ${ comment } ${ structString } ${ getFunction } () ${ field . Type } { \ n \ treturn ${ sname } ${ field . Parent } ${ field . Name } \ n} \ n ` ) ;
editor . insertSnippet ( ss , new vscode . Position ( this . info . Range [ 1 ] + 1 , 0 ) ) ;
}
2019-10-08 10:22:24 +00:00
}
}
} ) ;
}
} ) ;
}
} ;
obj . pick ( ) ;
}
}
2019-09-27 10:47:42 +00:00
2019-09-29 10:48:37 +00:00
function GetStruct ( ) : StructInfo | undefined {
let editor = vscode . window . activeTextEditor ;
if ( editor !== undefined ) {
if ( editor . document . languageId !== 'go' ) {
vscode . window . showInformationMessage ( 'file in the active editor is not a go file(*.go)' ) ;
return ;
}
let selection = editor . selection ;
// vscode.window.showInformationMessage( editor.document.version.toString() );
// vscode.window.showInformationMessage( text );
let selectline = selection . active . line ;
let regex = "type +([^ ]+) +struct" ;
// lineText.text.match()
for ( let i = selectline ; i >= 0 ; i -- ) {
let lineText = editor . document . lineAt ( i ) ;
let matchs = lineText . text . match ( regex ) ;
if ( matchs !== null ) {
let open = 0 ;
BREAK_OPEN : for ( let n = i ; n < editor . document . lineCount ; n ++ ) {
let lineText = editor . document . lineAt ( n ) ;
for ( let c = 0 ; c < lineText . text . length ; c ++ ) {
switch ( lineText . text [ c ] ) {
case '{' :
open ++ ;
break ;
case '}' :
open -- ;
if ( open === 0 ) {
if ( n >= selectline ) {
2019-09-30 10:38:01 +00:00
let structName = matchs [ 1 ] ;
2019-09-29 10:48:37 +00:00
return new StructInfo ( structName , getStructField ( editor , "" , i , n ) , [ i , n ] ) ;
}
break BREAK_OPEN ;
}
break ;
}
}
}
break ;
}
}
}
}
2019-09-27 10:47:42 +00:00
2019-09-29 10:48:37 +00:00
exports . activate = activate ;
function getStructField ( editor : vscode.TextEditor , parent : string , startline : number , endline : number ) : Field [ ] {
let result : Field [ ] = [ ] ;
if ( endline - startline <= 1 ) {
return result ;
}
parent += "." ;
2019-09-30 10:38:01 +00:00
2019-09-29 10:48:37 +00:00
let regex = "([^ \t]+)[ \t]+([^ \\(\\{\t]+)" ;
for ( let i = startline + 1 ; i < endline ; i ++ ) {
let textline = editor . document . lineAt ( i ) ;
let matchArray = textline . text . match ( regex ) ;
if ( matchArray !== null ) {
var end : number ;
let fieldName = matchArray [ matchArray . length - 2 ] ;
let fieldType = matchArray [ matchArray . length - 1 ] . trim ( ) ;
2019-09-30 10:38:01 +00:00
2019-09-29 10:48:37 +00:00
switch ( fieldType ) {
case 'struct' :
end = getFieldRange ( editor , [ '{' , '}' ] , i , endline ) ;
2019-09-30 10:38:01 +00:00
if ( i === end ) {
2019-09-29 10:48:37 +00:00
// let matches = textline.text.match("struct {0,}\\{[^ \t]+\\}");
function getSingleStructRelationship ( source : string , parent : string ) : Field | undefined {
let smatch = source . match ( "([^ \t]+)[^s]+struct {0,}\\{(.+)\\}" ) ;
2019-09-30 10:38:01 +00:00
if ( smatch !== null ) {
2019-10-08 10:22:24 +00:00
// console.log(smatch[0], smatch[1], smatch[2]);
2019-09-29 10:48:37 +00:00
return getSingleStructRelationship ( smatch [ 2 ] , parent + "." + smatch [ 1 ] ) ;
} else {
smatch = source . match ( "([^ \t]+)[ \t]+(.+)" ) ;
2019-09-30 10:38:01 +00:00
if ( smatch !== null ) {
return new Field ( parent + "." , smatch [ 2 ] . trim ( ) , smatch [ 1 ] , [ i , end ] ) ;
2019-09-29 10:48:37 +00:00
}
}
}
let v = getSingleStructRelationship ( textline . text , "" ) ;
2019-09-30 10:38:01 +00:00
if ( v !== undefined ) {
2019-09-29 10:48:37 +00:00
result . push ( v ) ;
}
} else {
2019-09-30 10:38:01 +00:00
result = result . concat ( getStructField ( editor , parent + fieldName , i , end ) ) ;
2019-09-29 10:48:37 +00:00
i = end ;
}
break ;
case 'interface' :
2019-09-30 10:38:01 +00:00
result . push ( new Field ( parent , fieldType + "{}" , fieldName , [ i , i ] ) ) ;
2019-09-29 10:48:37 +00:00
break ;
case 'func' :
end = getFieldRange ( editor , [ '(' , ')' ] , i , endline ) ;
2019-09-30 10:38:01 +00:00
if ( i === end ) {
2019-09-29 10:48:37 +00:00
let matches = textline . text . match ( "func\\(.+" ) ;
2019-09-30 10:38:01 +00:00
if ( matches !== null ) {
result . push ( new Field ( parent , matches [ 0 ] . trim ( ) , fieldName , [ i , end ] ) ) ;
2019-09-29 10:48:37 +00:00
}
2019-09-30 10:38:01 +00:00
} else {
2019-09-29 10:48:37 +00:00
i = end ;
}
break ;
default :
2019-09-30 10:38:01 +00:00
result . push ( new Field ( parent , fieldType , fieldName , [ i , i ] ) ) ;
2019-09-29 10:48:37 +00:00
break ;
}
}
}
return result ;
}
2019-09-27 10:47:42 +00:00
2019-09-29 10:48:37 +00:00
function getFieldRange ( editor : vscode.TextEditor , pair : string [ ] , startline : number , endline : number ) : number {
let open = 0 ;
let start = startline ;
let end = startline ;
BREAK_OPEN : for ( let n = start ; n < endline ; n ++ ) {
let lineText = editor . document . lineAt ( n ) ;
for ( let c = 0 ; c < lineText . text . length ; c ++ ) {
switch ( lineText . text [ c ] ) {
case pair [ 0 ] :
open ++ ;
break ;
case pair [ 1 ] :
open -- ;
if ( open === 0 ) {
end = n ;
break BREAK_OPEN ;
}
break ;
}
}
}
return end ;
2019-09-27 10:47:42 +00:00
}
2019-09-29 10:48:37 +00:00
// export function getStruct(editor: vscode.TextEditor) {
2019-09-27 10:47:42 +00:00
// }
// this method is called when your extension is deactivated
2019-09-29 10:48:37 +00:00
function deactivate() { }
exports . deactivate = deactivate ;