Beispiel #1
0
//Fixes Type and its' subtypes recursively
func (pp *packageParser) fixType(sym st.Symbol) {

	if sym == nil {
		panic("error: fixing nil symbol")
	}
	if st.IsPredeclaredIdentifier(sym.Name()) {
		return
	}

	if sym.PackageFrom() != pp.Package {
		return
	}
	// 	fmt.Printf("%s fixing %v %T %p\n", pp.Package.AstPackage.Name, sym.Name(), sym, sym)
	if pp.checkIsVisited(sym) {
		return
	}

	//fmt.Printf("%s fixing %v %T %p\n", pp.Package.AstPackage.Name, sym.Name(), sym,sym)

	switch t := sym.(type) {
	case *st.AliasTypeSymbol:
		pp.fixAliasTypeSymbol(t)
	case *st.PointerTypeSymbol:
		pp.fixPointerTypeSymbol(t)
	case *st.ArrayTypeSymbol:
		pp.fixArrayTypeSymbol(t)
	case *st.StructTypeSymbol:
		pp.fixStructTypeSymbol(t)
	case *st.InterfaceTypeSymbol:
		pp.fixInterfaceTypeSymbol(t)
	case *st.MapTypeSymbol:
		pp.fixMapTypeSymbol(t)
	case *st.ChanTypeSymbol:
		pp.fixChanTypeSymbol(t)
	case *st.FunctionTypeSymbol:
		pp.fixFunctionTypeSymbol(t)
	case *st.VariableSymbol:
		pp.fixVariableSymbol(t)
	case *st.FunctionSymbol:
		pp.fixFunctionSymbol(t)
	}
}
Beispiel #2
0
func renameSymbol(sym st.Symbol, newName string, programTree *program.Program) (fnames []string, fsets []*token.FileSet, files []*ast.File, err *errors.GoRefactorError) {
	filesMap := make(map[string]bool)
	for _, pos := range sym.Positions() {
		filesMap[pos.Filename] = true
	}
	l, i := len(filesMap), 0
	fnames, fsets, files = make([]string, l), make([]*token.FileSet, l), make([]*ast.File, l)
	for f, _ := range filesMap {
		fnames[i] = f
		i++
	}

	for i, f := range fnames {
		pack, file := programTree.FindPackageAndFileByFilename(f)
		positions := []token.Position{}
		for _, pos := range sym.Positions() {
			if pos.Filename == f {
				positions = append(positions, pos)
			}
		}
		if _, fsets[i], files[i], err = printerUtil.RenameIdents(pack.FileSet, programTree.IdentMap, f, file, positions, newName); err != nil {
			return nil, nil, nil, err
		}
	}
	for ident, _ := range sym.Identifiers() {
		ident.Name = newName
	}
	return fnames, fsets, files, nil
}
Beispiel #3
0
func (pp *packageParser) openMethodsAndFields(sym st.Symbol) {

	if pp.checkIsVisited(sym) {
		return
	}
	// 	fmt.Printf("opening %s %T from %s\n", sym.Name(), sym, func(p *st.Package) string {
	// 		if p == nil {
	// 			return "nil"
	// 		}
	// 		return p.AstPackage.Name
	// 	}(sym.PackageFrom()))

	if st.IsPredeclaredIdentifier(sym.Name()) {
		return
	}

	switch t := sym.(type) {
	case *st.ArrayTypeSymbol:
		pp.openMethodsAndFields(t.ElemType)
	case *st.ChanTypeSymbol:
		pp.openMethodsAndFields(t.ValueType)
	case *st.FunctionTypeSymbol:
		if t.Parameters != nil {
			t.Parameters.ForEachNoLock(func(sym st.Symbol) {
				v := sym.(*st.VariableSymbol)
				pp.openMethodsAndFields(v.VariableType)
			})
		}
		if t.Results != nil {
			t.Results.ForEachNoLock(func(sym st.Symbol) {
				v := sym.(*st.VariableSymbol)
				pp.openMethodsAndFields(v.VariableType)
			})
		}
	case *st.InterfaceTypeSymbol:
		if t.Meths != nil {
			t.Meths.ForEachNoLock(func(sym st.Symbol) {
				if _, ok := sym.(*st.FunctionSymbol); !ok {
					//EmbeddedInterface
					pp.openMethodsAndFields(sym)

					ts := sym.(*st.InterfaceTypeSymbol)
					t.Meths.AddOpenedScope(ts.Meths)
					//Delete functionSymbol which is now useles from interface
					t.Meths.RemoveSymbol(sym.Name())
				}
			})
		}
	case *st.MapTypeSymbol:
		pp.openMethodsAndFields(t.KeyType)
		pp.openMethodsAndFields(t.ValueType)
	case *st.StructTypeSymbol:
		// 		if t.Name() == "Package" {
		// 			fmt.Printf("YEAHHH YEAHHH %p\n", t)
		// 		}
		t.Fields.ForEachNoLock(func(variable st.Symbol) {
			if _, ok := variable.(*st.VariableSymbol); !ok {

				ts := variable.(st.ITypeSymbol)
				pp.openMethodsAndFields(ts)
				//Methods
				if ts.Methods() != nil {
					t.Methods().AddOpenedScope(ts.Methods())
				}
				//Fields
				switch ttt := ts.(type) {
				case *st.StructTypeSymbol:
					t.Fields.AddOpenedScope(ttt.Fields)
				case *st.PointerTypeSymbol:
					t.Fields.AddOpenedScope(ttt.Fields)

				}
				//No longer need in type thumb, replace with var
				typeVar := st.MakeVariable(ts.Name(), t.Fields, ts)
				typeVar.Idents = ts.Identifiers()
				typeVar.Posits = ts.Positions()
				t.Fields.ReplaceSymbol(ts.Name(), typeVar) //replaces old one
			}

		})
	case *st.PointerTypeSymbol:
		//fmt.Printf("%v %T \n", t.BaseType.Name(), t.BaseType)
		pp.openMethodsAndFields(t.BaseType)
		switch str := t.BaseType.(type) {
		case *st.StructTypeSymbol:
			t.Fields = str.Fields
		case *st.PointerTypeSymbol:
			t.Fields = str.Fields
		}

		if _, cyc := st.GetBaseType(t); cyc {
			// 			fmt.Printf("%s from %s\n", t.Name(), t.PackageFrom().AstPackage.Name)
			panic("cycle, don't work with that")
		}

		if t.BaseType.Methods() != nil {
			t.Methods().AddOpenedScope(t.BaseType.Methods())
		}
		// 		if t.BaseType.Name() == "Package" {
		// 			fmt.Printf("YEAHHH YEAHHH %p %p\n", t, t.BaseType)
		// 			fmt.Println(*t.Methods().String());
		// 		}
		pp.openMethodsAndFields(t.BaseType)
	}
}
Beispiel #4
0
func (pp *packageParser) registerIdent(sym st.Symbol, ident *ast.Ident) {
	sym.AddIdent(ident)
	pp.IdentMap.AddIdent(ident, sym)
	sym.AddPosition(pp.Package.FileSet.Position(ident.Pos()))
}
Beispiel #5
0
func Rename(filename string, line int, column int, newName string) (ok bool, err *errors.GoRefactorError) {

	if ok, err = CheckRenameParameters(filename, line, column, newName); !ok {
		return
	}

	programTree := parseProgram(filename)

	var sym st.Symbol
	if sym, err = programTree.FindSymbolByPosition(filename, line, column); err == nil {

		if _, ok := sym.(*st.PointerTypeSymbol); ok {
			panic("find by position returned pointer type!!!")
		}
		if st.IsPredeclaredIdentifier(sym.Name()) {
			return false, errors.UnrenamableIdentifierError(sym.Name(), " It's a basic language symbol")
		}
		if sym.PackageFrom().IsGoPackage {
			return false, errors.UnrenamableIdentifierError(sym.Name(), " It's a symbol,imported from go library")
		}
		if unicode.IsUpper(int(sym.Name()[0])) && !unicode.IsUpper(int(newName[0])) ||
			unicode.IsLower(int(sym.Name()[0])) && !unicode.IsLower(int(newName[0])) {
			return false, &errors.GoRefactorError{ErrorType: "Can't rename identifier", Message: "can't change access modifier. Changing first letter's case can cause errors."}
		}
		if _, ok := sym.Scope().LookUp(newName, filename); ok {
			return false, errors.IdentifierAlreadyExistsError(newName)
		}

		if meth, ok := sym.(*st.FunctionSymbol); ok {
			if meth.IsInterfaceMethod {
				return false, errors.UnrenamableIdentifierError(sym.Name(), " It's an interface method")
			}
		}
		if ps, ok := sym.(*st.PackageSymbol); ok {
			pack, file := programTree.FindPackageAndFileByFilename(filename)
			impDecl := findImportDecl(pack, file, ps)
			if impDecl == nil {
				panic("couldn't find import decl")
			}
			if impDecl.Name == nil || impDecl.Name.Name == "" {
				impDecl.Name = ast.NewIdent(newName)
			}
		}
		fnames, fsets, files, err := renameSymbol(sym, newName, programTree)
		if err == nil {
			for i, f := range fnames {
				programTree.SaveFileExplicit(f, fsets[i], files[i])
			}
		}
		return err == nil, err
	} else {
		return false, err
	}
	panic("unreachable code")
}