| 
									
										
										
										
											2016-04-14 18:18:24 +02:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package jsre | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"sort" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 	"github.com/dop251/goja" | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CompleteKeywords returns potential continuations for the given line. Since line is | 
					
						
							|  |  |  | // evaluated, callers need to make sure that evaluating line does not have side effects. | 
					
						
							|  |  |  | func (jsre *JSRE) CompleteKeywords(line string) []string { | 
					
						
							|  |  |  | 	var results []string | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 	jsre.Do(func(vm *goja.Runtime) { | 
					
						
							| 
									
										
										
										
											2016-02-20 14:28:34 +01:00
										 |  |  | 		results = getCompletions(vm, line) | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | 	return results | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | func getCompletions(vm *goja.Runtime, line string) (results []string) { | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | 	parts := strings.Split(line, ".") | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 	if len(parts) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 	// Find the right-most fully named object in the line. e.g. if line = "x.y.z" | 
					
						
							|  |  |  | 	// and "x.y" is an object, obj will reference "x.y". | 
					
						
							|  |  |  | 	obj := vm.GlobalObject() | 
					
						
							|  |  |  | 	for i := 0; i < len(parts)-1; i++ { | 
					
						
							|  |  |  | 		v := obj.Get(parts[i]) | 
					
						
							|  |  |  | 		if v == nil { | 
					
						
							|  |  |  | 			return nil // No object was found | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		obj = v.ToObject(vm) | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Go over the keys of the object and retain the keys matching prefix. | 
					
						
							|  |  |  | 	// Example: if line = "x.y.z" and "x.y" exists and has keys "zebu", "zebra" | 
					
						
							|  |  |  | 	// and "platypus", then "x.y.zebu" and "x.y.zebra" will be added to results. | 
					
						
							|  |  |  | 	prefix := parts[len(parts)-1] | 
					
						
							| 
									
										
										
										
											2016-02-15 16:42:39 +01:00
										 |  |  | 	iterOwnAndConstructorKeys(vm, obj, func(k string) { | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | 		if strings.HasPrefix(k, prefix) { | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 			if len(parts) == 1 { | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | 				results = append(results, k) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				results = append(results, strings.Join(parts[:len(parts)-1], ".")+"."+k) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-15 16:42:39 +01:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2016-02-20 14:58:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Append opening parenthesis (for functions) or dot (for objects) | 
					
						
							|  |  |  | 	// if the line itself is the only completion. | 
					
						
							|  |  |  | 	if len(results) == 1 && results[0] == line { | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 		obj := obj.Get(parts[len(parts)-1]) | 
					
						
							| 
									
										
										
										
											2016-02-20 14:58:06 +01:00
										 |  |  | 		if obj != nil { | 
					
						
							| 
									
										
										
										
											2020-01-27 11:50:48 +01:00
										 |  |  | 			if _, isfunc := goja.AssertFunction(obj); isfunc { | 
					
						
							| 
									
										
										
										
											2016-02-20 14:58:06 +01:00
										 |  |  | 				results[0] += "(" | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				results[0] += "." | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-15 14:56:26 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sort.Strings(results) | 
					
						
							|  |  |  | 	return results | 
					
						
							|  |  |  | } |