Exemplo n.º 1
0
func implementInterface(programTree *program.Program, filename string, line int, column int, varFile string, varLine int, varColumn int, asPointer bool) (bool, *errors.GoRefactorError) {
	if ok, err := CheckImplementInterfaceParameters(filename, line, column, varFile, varLine, varColumn); !ok {
		return false, err
	}
	packInt, _ := programTree.FindPackageAndFileByFilename(filename)
	if packInt == nil {
		return false, errors.ArgumentError("filename", "Program packages don't contain file '"+filename+"'")
	}
	packType, fileType := programTree.FindPackageAndFileByFilename(varFile)
	if packType == nil {
		return false, errors.ArgumentError("filename", "Program packages don't contain file '"+varFile+"'")
	}
	symInt, err := programTree.FindSymbolByPosition(filename, line, column)
	if err != nil {
		return false, err
	}
	symType, err := programTree.FindSymbolByPosition(varFile, varLine, varColumn)
	if err != nil {
		return false, err
	}

	sI, ok := symInt.(*st.InterfaceTypeSymbol)
	if !ok {
		return false, &errors.GoRefactorError{ErrorType: "implement interface error", Message: "symbol, pointed as interface, is actually not a one"}
	}
	if _, ok := symType.(*st.InterfaceTypeSymbol); ok {
		return false, &errors.GoRefactorError{ErrorType: "implement interface error", Message: "interface can't implement methods"}
	}
	sT, ok := symType.(st.ITypeSymbol)
	if !ok {
		return false, &errors.GoRefactorError{ErrorType: "implement interface error", Message: "interface can be implemented only by a type"}
	}
	if asPointer {
		sT = programTree.GetPointerType(sT)
	}

	errors := make([]*errors.GoRefactorError, 0, 10)
	missedMethods := make(map[*st.FunctionSymbol]bool)
	checker := func(sym st.Symbol) {
		f := sym.(*st.FunctionSymbol)
		ok, err := containsMethod(f, sT)
		if err != nil {
			errors = append(errors, err)
		} else if !ok {
			missedMethods[f] = true
		}
	}
	sI.Methods().ForEachNoLock(checker)
	sI.Methods().ForEachOpenedScope(func(table *st.SymbolTable) {
		table.ForEachNoLock(checker)
	})

	println("missedMethods:")
	for s, _ := range missedMethods {
		list := make([]ast.Stmt, 1)
		list[0] = &ast.ExprStmt{&ast.CallExpr{ast.NewIdent("panic"), token.NoPos, []ast.Expr{&ast.BasicLit{token.NoPos, token.STRING, "\"not implemented yet\""}}, token.NoPos, token.NoPos}}
		fdecl := makeFuncDecl(s.Name(), list, s.FunctionType.(*st.FunctionTypeSymbol).Parameters, nil, s.FunctionType.(*st.FunctionTypeSymbol).Results, st.MakeVariable(st.NO_NAME, sT.Scope(), sT), packType, varFile)
		printer.Fprint(os.Stdout, token.NewFileSet(), fdecl)
		println()
		fileType.Decls = append(fileType.Decls, fdecl)
	}
	println()
	println("errors:")
	for _, err := range errors {
		println(err.String())
	}

	return true, nil
}