From ac2707f5bb1a2219805bb73b4c8db7b3ec7714fd Mon Sep 17 00:00:00 2001 From: crekIron Date: Tue, 30 Mar 2021 22:48:48 +0530 Subject: [PATCH 1/9] making folder go and transferring code to it --- go/README.md | 19 + go/example/testExample.go | 69 +++ go/example/treatedExample.go | 40 ++ go/go.mod | 5 + go/go.sum | 37 ++ go/main.go | 24 + go/properties.json | 19 + go/src/piranha.go | 137 +++++ go/src/staleFlagCleaner.go | 624 ++++++++++++++++++++++ go/test/README.md | 4 + go/test/input/deepClean.go | 105 ++++ go/test/input/init.go | 58 ++ go/test/input/testConditional.go | 103 ++++ go/test/input/testExpressions.go | 107 ++++ go/test/input/testSwitch.go | 167 ++++++ go/test/output/control/deepClean.go | 97 ++++ go/test/output/control/init.go | 56 ++ go/test/output/control/testConditional.go | 53 ++ go/test/output/control/testExpressions.go | 66 +++ go/test/output/control/testSwitch.go | 97 ++++ go/test/output/treated/deepClean.go | 95 ++++ go/test/output/treated/init.go | 56 ++ go/test/output/treated/testConditional.go | 80 +++ go/test/output/treated/testExpressions.go | 83 +++ go/test/output/treated/testSwitch.go | 111 ++++ go/test/piranha_test.go | 146 +++++ 26 files changed, 2458 insertions(+) create mode 100644 go/README.md create mode 100644 go/example/testExample.go create mode 100644 go/example/treatedExample.go create mode 100644 go/go.mod create mode 100644 go/go.sum create mode 100644 go/main.go create mode 100644 go/properties.json create mode 100644 go/src/piranha.go create mode 100644 go/src/staleFlagCleaner.go create mode 100644 go/test/README.md create mode 100644 go/test/input/deepClean.go create mode 100644 go/test/input/init.go create mode 100644 go/test/input/testConditional.go create mode 100644 go/test/input/testExpressions.go create mode 100644 go/test/input/testSwitch.go create mode 100644 go/test/output/control/deepClean.go create mode 100644 go/test/output/control/init.go create mode 100644 go/test/output/control/testConditional.go create mode 100644 go/test/output/control/testExpressions.go create mode 100644 go/test/output/control/testSwitch.go create mode 100644 go/test/output/treated/deepClean.go create mode 100644 go/test/output/treated/init.go create mode 100644 go/test/output/treated/testConditional.go create mode 100644 go/test/output/treated/testExpressions.go create mode 100644 go/test/output/treated/testSwitch.go create mode 100644 go/test/piranha_test.go diff --git a/go/README.md b/go/README.md new file mode 100644 index 000000000..b3aaf43dc --- /dev/null +++ b/go/README.md @@ -0,0 +1,19 @@ +# PiranhaGo +PiranhaGo is runnable now. +Instructions:- +1. To build the package run `go build -o piranha`. Dependencies will install automatically and they are given in `go.mod` file. +2. Below are the instructions for running for the single file. +``` +Inputs from args +Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG [-treated] [-o OUTPUT] +Required arguments: + -s SOURCE_FILE: Path of the file to be refactored + -p PROPERTIES: Configuration file (json format) for Piranha. + -f STALE_FLAG: Name of the stale flag +Optional arguments: + -h: Show the options and exit. + -treated: If this is given, then flag is treated, + otherwise it is control. + -o OUTPUT: Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place. +``` +3. To do a test run, run piranha on `example/testExample.go`. Run `./piranha -p properties.json -s ./example/testExample.go -o ./example/treatedExample.go -f staleFlag` command in root directory. You will get your refracted file as `/example/treatedExample.go`. \ No newline at end of file diff --git a/go/example/testExample.go b/go/example/testExample.go new file mode 100644 index 000000000..3102ffbad --- /dev/null +++ b/go/example/testExample.go @@ -0,0 +1,69 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testExpressions(ge GoExamples) { + var x, y bool = false, false + + if ge.flagMthds.treatedBehaviour(staleFlag) || x { + fmt.Println("treated || of treatedBehaviour") + } else { + fmt.Println("control || of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && x { + fmt.Println("treated && of treatedBehaviour") + } else { + fmt.Println("control && of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && (x || y) { + fmt.Println("treated && of || of treatedBehaviour") + } else { + fmt.Println("control && of || of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && (x && y) { + fmt.Println("treated && of && of treatedBehaviour") + } else { + fmt.Println("control && of && of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && y == x { + fmt.Println("treated && equals of treatedBehaviour") + } else { + fmt.Println("control && equals of treatedBehaviour") + } + + if ge.flagMthds.controlBehaviour(staleFlag) || y == x { + fmt.Println("treated || equals of controlBehaviour") + } else { + fmt.Println("control || equals of controlBehaviour") + } + + if ge.flagMthds.controlBehaviour(staleFlag) && y && x { + fmt.Println("treated && and && of controlBehaviour") + } else { + fmt.Println("control && and && of controlBehaviour") + } + + if ge.flagMthds.controlBehaviour(staleFlag) || y || x { + fmt.Println("treated || && || of controlBehaviour") + } else { + fmt.Println("control || && || of controlBehaviour") + } + +} diff --git a/go/example/treatedExample.go b/go/example/treatedExample.go new file mode 100644 index 000000000..f37c1953f --- /dev/null +++ b/go/example/treatedExample.go @@ -0,0 +1,40 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testExpressions(ge GoExamples) { + var x, y bool = false, false + + if x { + fmt.Println("treated || of treatedBehaviour") + } else { + fmt.Println("control || of treatedBehaviour") + } + + fmt.Println("control && of treatedBehaviour") + fmt.Println("control && of || of treatedBehaviour") + fmt.Println("control && of && of treatedBehaviour") + fmt.Println("control && equals of treatedBehaviour") + fmt.Println("treated || equals of controlBehaviour") + + if y && x { + fmt.Println("treated && and && of controlBehaviour") + } else { + fmt.Println("control && and && of controlBehaviour") + } + + fmt.Println("treated || && || of controlBehaviour") +} diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 000000000..562f7b0c7 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,5 @@ +module github.com/PiranhaGo + +go 1.16 + +require github.com/dave/dst v0.26.2 diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 000000000..1de5b54be --- /dev/null +++ b/go/go.sum @@ -0,0 +1,37 @@ +github.com/dave/dst v0.26.2 h1:lnxLAKI3tx7MgLNVDirFCsDTlTG9nKTk7GcptKcWSwY= +github.com/dave/dst v0.26.2/go.mod h1:UMDJuIRPfyUCC78eFuB+SV/WI8oDeyFDvM/JR6NI3IU= +github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ= +github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/dave/kerr v0.0.0-20170318121727-bc25dd6abe8e/go.mod h1:qZqlPyPvfsDJt+3wHJ1EvSXDuVjFTK0j2p/ca+gtsb8= +github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWEmXBA= +github.com/google/pprof v0.0.0-20181127221834-b4f47329b966/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5 h1:MeC2gMlMdkd67dn17MEby3rGXRxZtWeiRXOnISfTQ74= +golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= diff --git a/go/main.go b/go/main.go new file mode 100644 index 000000000..523c9daf0 --- /dev/null +++ b/go/main.go @@ -0,0 +1,24 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package main + +import ( + "os" + + "github.com/PiranhaGo/src" +) + +func main() { + src.RunPiranha(os.Args) +} diff --git a/go/properties.json b/go/properties.json new file mode 100644 index 000000000..44414b07b --- /dev/null +++ b/go/properties.json @@ -0,0 +1,19 @@ +{ + "methodProperties": [ + { + "methodName": "treatedBehaviour", + "flagType": "treated", + "argumentIndex": 0 + }, + { + "methodName": "controlBehaviour", + "flagType": "control", + "argumentIndex": 0 + }, + { + "methodName": "commonBehaviour", + "flagType": "treated", + "argumentIndex": 1 + } + ] + } \ No newline at end of file diff --git a/go/src/piranha.go b/go/src/piranha.go new file mode 100644 index 000000000..6b09c90ce --- /dev/null +++ b/go/src/piranha.go @@ -0,0 +1,137 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package src + +import ( + "fmt" + "go/parser" + "go/token" + "log" + "os" + "strings" + + "github.com/dave/dst" + "github.com/dave/dst/decorator" +) + +/* +Inputs from args +Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG [-treated] [-o OUTPUT] +Required arguments: + -s SOURCE_FILE: Path of the file to be refactored + -p PROPERTIES: Configuration file (json format) for Piranha. + -f STALE_FLAG: Name of the stale flag +Optional arguments: + -h: Show the options and exit. + -treated: If this is given, then flag is treated, + otherwise it is control. + -o OUTPUT: Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place. +*/ +func help() { + //Help message + fmt.Println( + "Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG [-treated] [-o OUTPUT]", + "\nRequired arguments:", + "\n\t\t\t-s SOURCE_FILE: Path of the file to be refactored.", + "\n\t\t\t-p PROPERTIES: Configuration file (json format) for Piranha.", + "\n\t\t\t-f STALE_FLAG: Name of the stale flag.", + "\nOptional arguments:", + "\n\t\t\t-h: Show the options and exit.", + "\n\t\t\t-treated: If this is given, then flag is treated,", + "\n\t\t\totherwise it is control.", + "\n\t\t\t-o OUTPUT: Destination of the refactored output from piranha.", + "\n\t\t\tIf -o is not provided, then the source file is updated in place.") +} + +// RunPiranha : the main function for the piranha tool +func RunPiranha(inArgs []string) { + var sourceFile, configFile, flagName, outputFileName string = "", "", "", "" + var isTreated = false + sizeOfArgs := len(inArgs) + if len(inArgs) < 2 { + help() + return + } + for index, arg := range inArgs { + switch arg { + case "-h": + help() + return + case "-p": + if index+1 < sizeOfArgs { + configFile = inArgs[index+1] + if !strings.HasSuffix(configFile, ".json") { + return + } + } + case "-s": + if index+1 < sizeOfArgs { + sourceFile = inArgs[index+1] + if !strings.HasSuffix(sourceFile, ".go") { + return + } + } + case "-f": + if index+1 < sizeOfArgs { + flagName = inArgs[index+1] + } + case "-treated": + isTreated = true + case "-o": + if index+1 < sizeOfArgs { + outputFileName = inArgs[index+1] + } + default: + break + } + } + + if flagName == "" { + fmt.Println("Please provide a flag.") + } + if sourceFile == "" { + fmt.Println("Please provide a source file that is to be refactored.") + } + if configFile == "" { + fmt.Println("Please provide a config file. See README for more instructions.") + } + if flagName == "" || sourceFile == "" || configFile == "" { + fmt.Println("For more info, run ./piranha -h.") + return + } + + fs := token.NewFileSet() + parsed, err := decorator.ParseFile(fs, sourceFile, nil, parser.ParseComments) + if err != nil { + log.Fatal(err) + } + + var cleaner staleFlagCleaner + cleaner.init(configFile, flagName, isTreated) + newRoot := cleaner.run(parsed) + //////////////////////// + // For debugging purpose. It prints out the ast. + // spew.Dump(newRoot) + /////////////////////// + + if outputFileName == "" { + outputFileName = sourceFile + } + outputFile, err := os.Create(outputFileName) + /* + Here we are typecasting newRoot to dst.File.It is safe because the root of AST + always starts with the dst.File type. + */ + decorator.Fprint(outputFile, newRoot.(*dst.File)) +} diff --git a/go/src/staleFlagCleaner.go b/go/src/staleFlagCleaner.go new file mode 100644 index 000000000..19a3f88cd --- /dev/null +++ b/go/src/staleFlagCleaner.go @@ -0,0 +1,624 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package src + +import ( + "encoding/json" + "go/token" + "io/ioutil" + "log" + "os" + + /* + We have used dst package instead of official go ast package because ast package + does not keep positions of comment in place. So, we use dst package which keeps + the positions of comment in place. It is similiar to ast package and have same + functions as ast. So you can use documentation of ast to see the details of helper + functions. + */ + "github.com/dave/dst" + "github.com/dave/dst/dstutil" +) + +// API : For the type of API +type API int + +const ( + isTreated API = iota + isControl + isTesting + isUnknown +) + +// Methods : For json it is +type Methods struct { + Methods []FlagAPI `json:"methodProperties"` +} + +// FlagAPI : for getting the type from config file +type FlagAPI struct { + MethodName string `json:"methodName"` + OfType string `json:"flagType"` + FlagIndex int `json:"argumentIndex"` +} + +// Value : This is made to not confuse with true and false in code +type Value int + +const ( + isTrue Value = iota + isFalse + // This will be returned when you don't have to find true or false + isBot +) + +// Operator : To get the boolean operators +type Operator int + +const ( + and Operator = iota + or + not +) + +// Some useful global variable +var treated, control string = "treated", "control" +var strTrue, strFalse string = "true", "false" + +// Implementing this as whole class +type staleFlagCleaner struct { + configFile string + FlagAPIArr []FlagAPI + methods Methods + + /* + Here valueMap contains those which came from the stale function output. + It means that this will used for cleaning in Deep Clean Pass + */ + valueMap map[string]Value + functype map[string]FlagAPI + + flagName string + isTreated bool +} + +func (sfc *staleFlagCleaner) init(configFile string, flagName string, isTreated bool) { + sfc.configFile = configFile + sfc.flagName = flagName + sfc.isTreated = isTreated + sfc.valueMap = make(map[string]Value) + sfc.functype = make(map[string]FlagAPI) + sfc.ParseJSON() +} + +// Parse json +func (sfc *staleFlagCleaner) ParseJSON() { + + jsonFile, err := os.Open(sfc.configFile) + + if err != nil { + log.Fatalf("failed opening file: %s", err) + os.Exit(-1) + } + + byteValue, _ := ioutil.ReadAll(jsonFile) + + // we unmarshal our byteArray which contains our + // jsonFile's content into 'methodProperties' which we defined above + json.Unmarshal(byteValue, &sfc.methods) + // store it in a hashmap + for _, element := range sfc.methods.Methods { + sfc.functype[element.MethodName] = element + } +} + +// Gets the type of the flagAPI +func (sfc *staleFlagCleaner) flagTypeAPI(callExpr *dst.CallExpr) API { + var apiName string + var flagIndex int // -1 if flag or group not here + flagIndex = -1 + + for ind, expr := range callExpr.Args { + switch arg := expr.(type) { + case *dst.Ident: + if arg.Name == sfc.flagName { + flagIndex = ind + break + } + } + } + + switch d := callExpr.Fun.(type) { + case *dst.Ident: + apiName = d.Name + case *dst.SelectorExpr: + apiName = d.Sel.Name + default: + // other cases will come in future + } + + if element, ok := sfc.functype[apiName]; ok { + if element.FlagIndex == flagIndex { + switch element.OfType { + case treated: + return isTreated + case control: + return isControl + default: + return isUnknown + } + } + } + return isUnknown +} + +/* This function will evaluate all expression nodes here */ +func (sfc *staleFlagCleaner) evaluateExprNode(exprNode dst.Expr) Value { + + switch exprUnderConsideration := exprNode.(type) { + case *dst.Ident: + if val, ok := sfc.valueMap[exprUnderConsideration.Name]; ok { + return val + } + switch exprUnderConsideration.Name { + case strTrue: + return isTrue + case strFalse: + return isFalse + } + + // Handling expressions related to calling a function + case *dst.CallExpr: + // Get the type of API + typeOfAPI := sfc.flagTypeAPI(exprUnderConsideration) + // Hardcoding the output of some API types + if typeOfAPI == isTreated { + if sfc.isTreated { + return isTrue + } + return isFalse + } + if typeOfAPI == isControl { + if sfc.isTreated { + return isFalse + } + return isTrue + } + //Binary expressions + case *dst.BinaryExpr: + valX := sfc.evaluateExprNode(exprUnderConsideration.X) + valY := sfc.evaluateExprNode(exprUnderConsideration.Y) + if valX != isBot || valY != isBot { + switch exprUnderConsideration.Op { + case token.LAND: //stands for && + if valX == isFalse || valY == isFalse { + return isFalse + } + if valX == isTrue && valY == isTrue { + return isTrue + } + case token.LOR: //stands for || + if valX == isTrue || valY == isTrue { + return isTrue + } + if valX == isFalse && valY == isFalse { + return isFalse + } + case token.EQL: + if valX != isBot && valY != isBot { + if valX == valY { + return isTrue + } + return isFalse + } + + case token.NEQ: + if valX == valY { + return isFalse + } + return isTrue + } + } + //Unary expressions + case *dst.UnaryExpr: + switch exprUnderConsideration.Op { + case token.NOT: + valX := sfc.evaluateExprNode(exprUnderConsideration.X) + switch valX { + case isTrue: + return isFalse + case isFalse: + return isTrue + } + case token.AND: // &expr + return sfc.evaluateExprNode(exprUnderConsideration.X) + default: + //do nothing for now. + } + //Star expression (*expr) + case *dst.StarExpr: + return sfc.evaluateExprNode(exprUnderConsideration.X) + //Paren Expr: exprs inside parenthesis + case *dst.ParenExpr: + return sfc.evaluateExprNode(exprUnderConsideration.X) + + //Selector Expr (expr.A, a.b, etc.) + case *dst.SelectorExpr: + switch ident := exprUnderConsideration.X.(type) { + case *dst.Ident: + if val, ok := sfc.valueMap[ident.Name+"."+exprUnderConsideration.Sel.Name]; ok { + return val + } + default: + //Do nothing for now + } + + default: + //Do nothing for now + } + + return isBot +} + +// This is the pre function of the dstutil.Apply +/* +From documentation: +If pre is not nil, it is called for each node before the node's children are +traversed (pre-order). If pre returns false, no children are traversed, and +not called for that node. +*/ +func (sfc *staleFlagCleaner) pre(n *dstutil.Cursor) bool { + return true +} + +func (sfc *staleFlagCleaner) checkForBoolLiterals(value dst.Expr) bool { + switch checkval := value.(type) { + case *dst.Ident: + if checkval.Name == strTrue || checkval.Name == strFalse { + //do nothing + return true + } + default: + return false + } + return false +} + +/* +Below function have this aim: +If Value is isBot or it is a bool literal, then we are not adding that to valueMap +if not then will add to valueMap. +This signifies whether variable has effect of flag or not. +*/ +func (sfc *staleFlagCleaner) updateValueMapPost(name dst.Expr, value dst.Expr) { + valOfExpr := sfc.evaluateExprNode(value) + doNotDelLiterals := sfc.checkForBoolLiterals(value) + switch d := name.(type) { + case *dst.Ident: + if valOfExpr == isBot || doNotDelLiterals { + if _, ok := sfc.valueMap[d.Name]; ok { + delete(sfc.valueMap, d.Name) + } + } else { + sfc.valueMap[d.Name] = valOfExpr + } + case *dst.SelectorExpr: + switch ident := d.X.(type) { + case *dst.Ident: + if valOfExpr == isBot || doNotDelLiterals { + if _, ok := sfc.valueMap[ident.Name+"."+d.Sel.Name]; ok { + delete(sfc.valueMap, ident.Name+"."+d.Sel.Name) + } + } else { + sfc.valueMap[ident.Name+"."+d.Sel.Name] = valOfExpr + } + default: + //Do nothing for now + } + default: + // other cases may come here in future + } +} + +/* +It will deal with *dst.ValueSpec. Values of variable stored in valueMap +will be deleted from node. +*/ +func (sfc *staleFlagCleaner) DelValStmt(names *[]*dst.Ident, values *[]dst.Expr) bool { + valOfExpr := isBot + delCallExpr := false + doNotDelLiterals := false + for ind := 0; ind < len((*names)); ind++ { + delCallExpr = false + doNotDelLiterals = false + if len((*values)) != 0 { + valOfExpr = sfc.evaluateExprNode((*values)[ind]) + doNotDelLiterals = sfc.checkForBoolLiterals((*values)[ind]) + sfc.updateValueMapPost((*names)[ind], (*values)[ind]) + } + + if (valOfExpr != isBot && !doNotDelLiterals) || (*names)[ind].Name == sfc.flagName || delCallExpr { + if len((*values)) != 0 { + var trueIdent dst.Ident + if valOfExpr == isTrue { + trueIdent.Name = strTrue + } else { + trueIdent.Name = strFalse + } + (*values)[ind] = dst.Expr(&trueIdent) + } + if len((*names)) <= 1 { + return true + } + } + valOfExpr = isBot + } + if len((*names)) == 0 { + return true + } + return false +} + +/* +It will deal with *dst.AssignStmt. Values of variable stored in valueMap +will be deleted from node. +*/ +func (sfc *staleFlagCleaner) DelAssStmt(names *[]dst.Expr, values *[]dst.Expr) bool { + valOfExpr := isBot + delCallExpr := false + doNotDelLiterals := false + for ind := 0; ind < len((*names)); ind++ { + //check if name is in valueName + valOfExpr = sfc.evaluateExprNode((*values)[ind]) + delCallExpr = false + + doNotDelLiterals = sfc.checkForBoolLiterals((*values)[ind]) + + // Need to see what to do with this thing + sfc.updateValueMapPost((*names)[ind], (*values)[ind]) + + if (valOfExpr != isBot && !doNotDelLiterals) || delCallExpr { + var trueIdent dst.Ident + if valOfExpr == isTrue { + trueIdent.Name = strTrue + } else { + trueIdent.Name = strFalse + } + (*values)[ind] = dst.Expr(&trueIdent) + if len((*names)) <= 1 { + return true + } + } + } + if len((*names)) == 0 { + return true + } + return false +} + +// This is the post function of the dstutil.Apply +/* +From documentation: +If post is not nil, and a prior call of pre didn't return false, post is +called for each node after its children are traversed (post-order). If +post returns false, traversal is terminated and Apply returns immediately. + +Working: +This wiil be used to delete the nodes and storing the values of expressions. +*/ +func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { + switch d := n.Node().(type) { + case *dst.ValueSpec: + //need for loop here to delete the specific varible in + delVal := sfc.DelValStmt(&d.Names, &d.Values) + if delVal { + n.Delete() + } + //GenDecl + case *dst.GenDecl: + if len(d.Specs) == 0 { + switch n.Parent().(type) { + case *dst.DeclStmt: + //wait Decl stmt + default: + n.Delete() + } + } + //declstmt + case *dst.DeclStmt: + if gd := d.Decl.(*dst.GenDecl); gd.Tok == token.VAR { + if len(gd.Specs) == 0 { + n.Delete() + } + } + + //Assignment statements + case *dst.AssignStmt: + //then delete from slice + sfc.DelAssStmt(&d.Lhs, &d.Rhs) + + //If cond statements + case *dst.IfStmt: + // Init of Ifstmt will get handled in assignStmt + // Now evaluate the cond. Cond is already refactored due to pre-order traversal. + cond := sfc.evaluateExprNode(d.Cond) + if cond != isBot { + if cond == isFalse { + if d.Else != nil { + for _, a := range d.Else.(*dst.BlockStmt).List { + n.InsertBefore(a) + } + } + } else { + for _, a := range d.Body.List { + n.InsertBefore(a) + } + } + n.Delete() + } + //Switch statements + case *dst.SwitchStmt: + // Init of switchstmt will get handled in assignStmt + if d.Tag != nil { + valExpr := sfc.evaluateExprNode(d.Tag) + if valExpr != isBot { + notfoundCase := false + for _, exprstmt := range d.Body.List { + if exprstmt.(*dst.CaseClause).List != nil { //nil means default case + valCaseClause := sfc.evaluateExprNode(exprstmt.(*dst.CaseClause).List[0]) + if valCaseClause == valExpr { + //this has to go out as switch is going to delete + for _, bodyEle := range exprstmt.(*dst.CaseClause).Body { + n.InsertBefore(bodyEle) + } + notfoundCase = false + break + } else { + notfoundCase = true + } + } else { + //default case + //here assuming defualt case is at last + if notfoundCase { + for _, bodyEle := range exprstmt.(*dst.CaseClause).Body { + n.InsertBefore(bodyEle) + } + } + } + } + n.Delete() + } + } else { + //now switch is like elseif statements so do accordingly + needDeletion := false + isBotAbove := false + for ind := 0; ind < len(d.Body.List); ind++ { + exprstmt := d.Body.List[ind] + if exprstmt.(*dst.CaseClause).List != nil { + valCaseClause := sfc.evaluateExprNode(exprstmt.(*dst.CaseClause).List[0]) + if valCaseClause == isTrue { + //this has to go out as switch is going to delete + //On the condition that there was no expression above whose value is isBot. + if !isBotAbove { + for _, bodyEle := range exprstmt.(*dst.CaseClause).Body { + n.InsertBefore(bodyEle) + } + needDeletion = true + break + } else { + d.Body.List = d.Body.List[:ind+1] + d.Body.List[ind].(*dst.CaseClause).List = nil + break + } + } else if valCaseClause == isFalse { + if len(d.Body.List) > 1 { + copy(d.Body.List[ind:], d.Body.List[ind+1:]) // Shift d.Body.List[ind+1:] left one index. + d.Body.List[len(d.Body.List)-1] = nil // Erase last element (write zero value). + d.Body.List = d.Body.List[:len(d.Body.List)-1] // Truncate slice. + + ind = ind - 1 + } else { + n.Delete() + break + } + } else { + // so now value is bot + isBotAbove = true + } + } + } + if needDeletion { + n.Delete() + } + } + //handling for in general experssions + case *dst.BinaryExpr: + valX := sfc.evaluateExprNode(d.X) + valY := sfc.evaluateExprNode(d.Y) + if valX == isBot || valY == isBot { + if valX == isBot && valY == isBot { + //do nothing + } else { + //now one of them is not bot + //check for valX + if valX == isTrue && d.Op != token.LOR { + n.Replace(d.Y) + } + if valX == isFalse && d.Op != token.LAND { + n.Replace(d.Y) + } + if valY == isTrue && d.Op != token.LOR { + n.Replace(d.X) + } + if valY == isFalse && d.Op != token.LAND { + n.Replace(d.X) + } + if d.Op == token.EQL { + newNode := n.Node() + var trueIdent dst.Ident + // either valX is not bot or valY. both cannot be bot at the same time as we checked out above + if valX != isBot { + if valX == isTrue { + trueIdent.Name = strTrue + } else { + trueIdent.Name = strFalse + } + newNode.(*dst.BinaryExpr).X = dst.Expr(&trueIdent) + n.Replace(newNode) + } else { + if valY == isTrue { + trueIdent.Name = strTrue + } else { + trueIdent.Name = strFalse + } + newNode.(*dst.BinaryExpr).Y = dst.Expr(&trueIdent) + n.Replace(newNode) + } + } + } + } + default: + + } + return true +} + +// This is the Upper flow of the programme +/* +Input: Parsed File(dst.Node) +Output: New Parser File(dst.Node) + +FLOW OF THE FUNCTION: + +This will take parsed file which will contain all comments. +Walk the tree with apply. In Pre function get values of variable and fucntion +returns that are related to the flag. In Post funtion will delete the nodes +according to the conditions. Also, this will store elements for doing deep +clean pass. + +Additional thought: + +Thinking of adding deep clean functionality in here after completing the +First Phase of the code. +*/ +func (sfc *staleFlagCleaner) run(root dst.Node) dst.Node { + /* + From documentation: + Apply traverses a syntax tree recursively, starting with root, and + calling pre and post for each node as described below. Apply returns + the syntax tree, possibly modified. + */ + modifiedRoot := dstutil.Apply(root, sfc.pre, sfc.post) + return modifiedRoot +} diff --git a/go/test/README.md b/go/test/README.md new file mode 100644 index 000000000..ef748804b --- /dev/null +++ b/go/test/README.md @@ -0,0 +1,4 @@ +# Testing of PiranhaGo +1. Run `go test` in this directory to test the working of Piranha. +2. `input` directory contains test cases that are used for testing. +3. `output` directory contains two subdirectories `treated` and `control`. When `piranha` is run **with** flag `-treated` on a test file in `input`, it generates refactored code that will match with the corresponding file in `output/treated`. Similarly, if `piranha` is run **without** flag `-treated`, then it will generate output that matches the corresponding file in `output/control`. diff --git a/go/test/input/deepClean.go b/go/test/input/deepClean.go new file mode 100644 index 000000000..f04ca65d4 --- /dev/null +++ b/go/test/input/deepClean.go @@ -0,0 +1,105 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +// A defer statement defers the execution of a function until the surrounding function returns. +func (ge GoExamples) useOfDefer() bool { + defer ge.storeuseInit() + return true +} + +func (ge GoExamples) storeuseBefore() { + /* + TODO: There is work going on to add the deep clean feature. + In this case the first if statment should be treated because + ge.basicFeature value may get affected by stale feature flag. + */ + if ge.basicFeature { + fmt.Println("Hi basicFeature") + } + if ge.localService { + fmt.Println("hi localService") + } + if ge.newFeatures { + fmt.Println("hi newFeatures") + } + + if !ge.localService { + fmt.Println("not localService") + } else { + fmt.Println("localService") + } + + if ge.localService && ge.newFeatures { + fmt.Println("localService and newFeatures") + } + + if ge.newFeatures { + fmt.Println("newFeatures") + } +} + +// This function is also acting as a pointer reciever +// Methods with pointer receivers can modify the value to which the receiver points +// This also using above two functions +func (ge *GoExamples) storeuseInit() { + ge.basicFeature = ge.flagMthds.treatedBehaviour(staleFlag) + ge.localService = ge.flagMthds.controlBehaviour(localFlag) + ge.newFeatures = ge.flagMthds.treatedBehaviour(newFlag) + + pointerfieldX := &ge.basicFeature + pointerfieldY := &ge.localService + + if ge.basicFeature { + fmt.Println("I initialised basicFeature") + } + + if ge.localService { + fmt.Println("I initialised localService") + } + + //testing pointer. I think need more test cases like this + if *pointerfieldX || !*pointerfieldY { + fmt.Println("pointers to be treated/not treated") + } +} + +func (ge GoExamples) storeuseAfter() { + // I love basicFeature + if ge.basicFeature { + fmt.Println("Hi basicFeature again") + } + if ge.localService { + fmt.Println("hi localService again") + } + if ge.newFeatures { + fmt.Println("hi newFeatures again") + } + + if !ge.localService { + fmt.Println("not localService again") + } else { + fmt.Println("localService again") + } + + if ge.localService && ge.newFeatures { + fmt.Println("localService and newFeatures again") + } + + if ge.newFeatures { + fmt.Println("newFeatures again") + } +} diff --git a/go/test/input/init.go b/go/test/input/init.go new file mode 100644 index 000000000..008135193 --- /dev/null +++ b/go/test/input/init.go @@ -0,0 +1,58 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +// PropFlag :defining a type for flag +type PropFlag int + +// This contatins flags +// This works like enum in golang +// If we got any other implementation of flags then we will see on that in future +const ( + //comment0 + globalFlag PropFlag = iota //comment1 + //comment2 + staleFlag //comment3 + //comment4 + localFlag + newFlag +) + +// FlagMethods : This will contains treatment and control methods +type FlagMethods struct { +} + +func (flgMthd FlagMethods) treatedBehaviour(flag PropFlag) bool { + return true +} +func (flgMthd FlagMethods) controlBehaviour(flag PropFlag) bool { + return true +} +func (flgMthd FlagMethods) commonBehaviour(str string, flag2 PropFlag) bool { + return true +} + +// GoExamples : This will act as a class +type GoExamples struct { + flagMthds FlagMethods + + localService, globalService, newFeatures, basicFeature bool +} + +func globalFeature(flag PropFlag) bool { + if flag == globalFlag { + return true + } + return false +} diff --git a/go/test/input/testConditional.go b/go/test/input/testConditional.go new file mode 100644 index 000000000..d36b2cc25 --- /dev/null +++ b/go/test/input/testConditional.go @@ -0,0 +1,103 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testIfConditionalAndInitExpressions(ge GoExamples) { + // Treated Control behaviour will be governed by three or more flags + if ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag) { + fmt.Println("treat1") + } else { + fmt.Println("control1") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag) { + fmt.Println("treat2") + } else { + fmt.Println("control2") + } + + if globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) { + fmt.Println("treat3") + } else { + fmt.Println("control3") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) || ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag) { + fmt.Println("treat1 with ||") + } else { + fmt.Println("control1 with ||") + } + + if ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag) { + fmt.Println("treat4") + } else { + fmt.Println("control4") + } + + if ge.flagMthds.controlBehaviour(staleFlag) || globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag) { + fmt.Println("treat5") + } else { + fmt.Println("control5") + } + + if globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) { + fmt.Println("treat6") + } else { + fmt.Println("control6") + } + + if ge.flagMthds.controlBehaviour(staleFlag) && ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag) { + fmt.Println("treat4 with &&") + } else { + fmt.Println("control4 with &&") + } + + //comment1 + a := ge.flagMthds.commonBehaviour("user", staleFlag) //comment2 + //comment3 + b := ge.flagMthds.treatedBehaviour(newFlag) //comment4 + //comment5 + if a && b { + fmt.Println("treat4 on a && b") + } else { + fmt.Println("control4 on a && b") + } + + if a || b { + fmt.Println("treat5 on a || b") + } else { + fmt.Println("control5 on a || b") + } + + if v := ge.flagMthds.treatedBehaviour(staleFlag); v { + fmt.Println("treat6 with v") + } else { + fmt.Println("control6 with v") + } + + if v := ge.flagMthds.treatedBehaviour(staleFlag); v == true { + b = a && b && !b + fmt.Println("treat7 with v") + } else { + fmt.Println("control7 with v") + } + + if v := ge.flagMthds.treatedBehaviour(staleFlag); v != true { + fmt.Println("treat8 with v") + } else { + fmt.Println("control8 with v") + } +} diff --git a/go/test/input/testExpressions.go b/go/test/input/testExpressions.go new file mode 100644 index 000000000..919276a9f --- /dev/null +++ b/go/test/input/testExpressions.go @@ -0,0 +1,107 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testExpressions(ge GoExamples) { + if ge.flagMthds.treatedBehaviour(staleFlag) { + fmt.Println("treated behaviour of treatedBehaviour") + } else { + fmt.Println("control behaviour of treatedBehaviour") + } + + //global feature is not in properties right now. So this should not get treated + if globalFeature(staleFlag) { + fmt.Println("global treated behaviour") + } else { + fmt.Println("global control behaviour") + } + + if ge.flagMthds.controlBehaviour(staleFlag) { + fmt.Println("treated behaviour of controlBehaviour") + } else { + fmt.Println("control behaviour of controlBehaviour") + } + var x, y bool = false, false + + if ge.flagMthds.treatedBehaviour(staleFlag) || x { + fmt.Println("treated || of treatedBehaviour") + } else { + fmt.Println("control || of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && x { + fmt.Println("treated && of treatedBehaviour") + } else { + fmt.Println("control && of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && (x || y) { + fmt.Println("treated && of || of treatedBehaviour") + } else { + fmt.Println("control && of || of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && (x && y) { + fmt.Println("treated && of && of treatedBehaviour") + } else { + fmt.Println("control && of && of treatedBehaviour") + } + + if ge.flagMthds.treatedBehaviour(staleFlag) && y == x { + fmt.Println("treated && equals of treatedBehaviour") + } else { + fmt.Println("control && equals of treatedBehaviour") + } + + if ge.flagMthds.controlBehaviour(staleFlag) || y == x { + fmt.Println("treated || equals of controlBehaviour") + } else { + fmt.Println("control || equals of controlBehaviour") + } + + if ge.flagMthds.controlBehaviour(staleFlag) && y && x { + fmt.Println("treated && and && of controlBehaviour") + } else { + fmt.Println("control && and && of controlBehaviour") + } + + if ge.flagMthds.controlBehaviour(staleFlag) || y || x { + fmt.Println("treated || && || of controlBehaviour") + } else { + fmt.Println("control || && || of controlBehaviour") + } + + y = ge.flagMthds.treatedBehaviour(staleFlag) + y = ge.flagMthds.controlBehaviour(staleFlag) && x + y = ge.flagMthds.treatedBehaviour(staleFlag) || x + + if y { + fmt.Println("y cleaned, so treated behaviour") + } else { + fmt.Println("y cleaned, so you see control behaviour") + } + + y = ge.flagMthds.treatedBehaviour(staleFlag) && y == x + // This is done on purpose to check deep clean work + y = ge.flagMthds.treatedBehaviour(staleFlag) + + if y { + fmt.Println("y not cleaned, so treated behaviour") + } else { + fmt.Println("y not cleaned, so control behaviour") + } + +} diff --git a/go/test/input/testSwitch.go b/go/test/input/testSwitch.go new file mode 100644 index 000000000..ad33a9af5 --- /dev/null +++ b/go/test/input/testSwitch.go @@ -0,0 +1,167 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testSwitch(ge GoExamples) { + switch os := ge.flagMthds.treatedBehaviour(staleFlag); os { + case true: + fmt.Println("mike treat 1") + default: + fmt.Println("defaulter 1") + } + + switch os := ge.flagMthds.treatedBehaviour(newFlag); os { + case true: + fmt.Println("mike treat 2") + default: + fmt.Println("defaulter 2") + } + + switch !ge.flagMthds.treatedBehaviour(staleFlag) { + case true: + fmt.Println("mike treat 3") + default: + fmt.Println("defaulter 3") + } + + switch os := ge.flagMthds.controlBehaviour(staleFlag); os { + case true: + fmt.Println("mike treat 4") + default: + fmt.Println("defaulter 4") + } + + x := true + y := false + + switch os := ge.flagMthds.treatedBehaviour(staleFlag) && (x || y); os { + case true: + fmt.Println("mike treat 5") + default: + fmt.Println("defaulter 5") + } + + switch os := ge.flagMthds.treatedBehaviour(staleFlag); os && (x || y) { + case true: + fmt.Println("mike treat 6") + default: + fmt.Println("mike control 6") + } + + switch os := ge.flagMthds.controlBehaviour(staleFlag); os && (x || y) { + case true: + fmt.Println("mike treat 7") + default: + fmt.Println("mike control 7") + } + + switch ge.flagMthds.treatedBehaviour(staleFlag) || x || y { + case true: + print("treated") + x = !ge.flagMthds.treatedBehaviour(staleFlag) || y + case false: + print("control") + y = !ge.flagMthds.treatedBehaviour(staleFlag) || x + } + + switch ge.flagMthds.controlBehaviour(staleFlag) && x && y { + case true: + fmt.Println("all are true") + case false: + fmt.Println("someone is false") + } + + /* + If you are familiar with go progamming then you probably know that + this style of writing switch statments is like writing if-elseif-else + statements in C, C++, Java or Python. + + So, to refactor this code we will consider three cases: + (ith case statement means position of the case statement from first case) + + Case1: + If ith case statement evaluates to true and all case statements + above this statement evaluates to false. (This also includes if 1st case + statement evaluates to true). + Do: + Then we will remove whole switch statment and replace it with body + of ith case statment. + + Case2: + If ith case statement evaluates to true and all case statements + above this statement evaluates to isBot(it means cannot determine + whether it is true or false). + Do: + Then we will remove all the cases below the ith case statement and + rewrite the switch statement with ith case statment as default. (check + corresponding refactored output without -treated of this file in + 'output/control' directory.) + + Case3: + If ith case statment is false. + Do: + Then remove it from the switch statement in refactored output. + */ + + x = true + y = false + + // Switch 1 + switch { + case ge.flagMthds.treatedBehaviour(staleFlag) || x: + fmt.Println("switch test 1") + case ge.flagMthds.treatedBehaviour(staleFlag) && x: + fmt.Println("switch test 2") + case ge.flagMthds.treatedBehaviour(staleFlag) && (x || y): + fmt.Println("switch test 3") + case ge.flagMthds.treatedBehaviour(staleFlag) && (x && y): + fmt.Println("switch test 4") + case ge.flagMthds.treatedBehaviour(staleFlag) && y == x: + fmt.Println("switch test 5") + x = y || ge.flagMthds.treatedBehaviour(newFlag) + case ge.flagMthds.controlBehaviour(staleFlag) || y == x: + fmt.Println("switch test 6") + case ge.flagMthds.controlBehaviour(staleFlag) && y && x: + fmt.Println("switch test 7") + case ge.flagMthds.controlBehaviour(staleFlag) || y || x: + fmt.Println("switch test 8") + } + + // Switch 2 + switch { + case ge.flagMthds.treatedBehaviour(staleFlag) && x: + fmt.Println("switch test 9") + case ge.flagMthds.treatedBehaviour(staleFlag) && (x || y): + fmt.Println("switch test 10") + case ge.flagMthds.treatedBehaviour(staleFlag) && (x && y): + fmt.Println("switch test 11") + case ge.flagMthds.treatedBehaviour(staleFlag) && y == x: + fmt.Println("switch test 12") + x = y || ge.flagMthds.treatedBehaviour(newFlag) + case ge.flagMthds.controlBehaviour(staleFlag) || y == x: + fmt.Println("switch test 13") + case ge.flagMthds.controlBehaviour(staleFlag) && y && x: + fmt.Println("switch test 14") + case ge.flagMthds.controlBehaviour(staleFlag) || y || x: + fmt.Println("switch test 15") + } + + // Switch 3 + switch { + case ge.flagMthds.controlBehaviour(staleFlag) && y && x: + fmt.Println("switch test 16") + } +} diff --git a/go/test/output/control/deepClean.go b/go/test/output/control/deepClean.go new file mode 100644 index 000000000..6fbd7469a --- /dev/null +++ b/go/test/output/control/deepClean.go @@ -0,0 +1,97 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +// A defer statement defers the execution of a function until the surrounding function returns. +func (ge GoExamples) useOfDefer() bool { + defer ge.storeuseInit() + return true +} + +func (ge GoExamples) storeuseBefore() { + /* + TODO: There is work going on to add the deep clean feature. + In this case the first if statment should be treated because + ge.basicFeature value may get affected by stale feature flag. + */ + if ge.basicFeature { + fmt.Println("Hi basicFeature") + } + if ge.localService { + fmt.Println("hi localService") + } + if ge.newFeatures { + fmt.Println("hi newFeatures") + } + + if !ge.localService { + fmt.Println("not localService") + } else { + fmt.Println("localService") + } + + if ge.localService && ge.newFeatures { + fmt.Println("localService and newFeatures") + } + + if ge.newFeatures { + fmt.Println("newFeatures") + } +} + +// This function is also acting as a pointer reciever +// Methods with pointer receivers can modify the value to which the receiver points +// This also using above two functions +func (ge *GoExamples) storeuseInit() { + ge.basicFeature = false + ge.localService = ge.flagMthds.controlBehaviour(localFlag) + ge.newFeatures = ge.flagMthds.treatedBehaviour(newFlag) + + pointerfieldX := false + pointerfieldY := &ge.localService + + if ge.localService { + fmt.Println("I initialised localService") + } + + //testing pointer. I think need more test cases like this + if !*pointerfieldY { + fmt.Println("pointers to be treated/not treated") + } +} + +func (ge GoExamples) storeuseAfter() { + if ge.localService { + fmt.Println("hi localService again") + } + if ge.newFeatures { + fmt.Println("hi newFeatures again") + } + + if !ge.localService { + fmt.Println("not localService again") + } else { + fmt.Println("localService again") + } + + if ge.localService && ge.newFeatures { + fmt.Println("localService and newFeatures again") + } + + if ge.newFeatures { + fmt.Println("newFeatures again") + } +} diff --git a/go/test/output/control/init.go b/go/test/output/control/init.go new file mode 100644 index 000000000..d8b4eaeb0 --- /dev/null +++ b/go/test/output/control/init.go @@ -0,0 +1,56 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +// PropFlag :defining a type for flag +type PropFlag int + +// This contatins flags +// This works like enum in golang +// If we got any other implementation of flags then we will see on that in future +const ( + //comment0 + globalFlag PropFlag = iota //comment1 + //comment4 + localFlag + newFlag +) + +// FlagMethods : This will contains treatment and control methods +type FlagMethods struct { +} + +func (flgMthd FlagMethods) treatedBehaviour(flag PropFlag) bool { + return true +} +func (flgMthd FlagMethods) controlBehaviour(flag PropFlag) bool { + return true +} +func (flgMthd FlagMethods) commonBehaviour(str string, flag2 PropFlag) bool { + return true +} + +// GoExamples : This will act as a class +type GoExamples struct { + flagMthds FlagMethods + + localService, globalService, newFeatures, basicFeature bool +} + +func globalFeature(flag PropFlag) bool { + if flag == globalFlag { + return true + } + return false +} diff --git a/go/test/output/control/testConditional.go b/go/test/output/control/testConditional.go new file mode 100644 index 000000000..a575f2dec --- /dev/null +++ b/go/test/output/control/testConditional.go @@ -0,0 +1,53 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testIfConditionalAndInitExpressions(ge GoExamples) { + fmt.Println("control1") + fmt.Println("control2") + fmt.Println("control3") + + if ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag) { + fmt.Println("treat1 with ||") + } else { + fmt.Println("control1 with ||") + } + fmt.Println("treat4") + fmt.Println("treat5") + fmt.Println("treat6") + + if ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag) { + fmt.Println("treat4 with &&") + } else { + fmt.Println("control4 with &&") + } + + //comment1 + a := false //comment2 + //comment3 + b := ge.flagMthds.treatedBehaviour(newFlag) //comment4 + fmt.Println("control4 on a && b") + + if b { + fmt.Println("treat5 on a || b") + } else { + fmt.Println("control5 on a || b") + } + + fmt.Println("control6 with v") + fmt.Println("control7 with v") + fmt.Println("treat8 with v") +} diff --git a/go/test/output/control/testExpressions.go b/go/test/output/control/testExpressions.go new file mode 100644 index 000000000..efdbad6c8 --- /dev/null +++ b/go/test/output/control/testExpressions.go @@ -0,0 +1,66 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testExpressions(ge GoExamples) { + fmt.Println("control behaviour of treatedBehaviour") + + //global feature is not in properties right now. So this should not get treated + if globalFeature(staleFlag) { + fmt.Println("global treated behaviour") + } else { + fmt.Println("global control behaviour") + } + + fmt.Println("treated behaviour of controlBehaviour") + var x, y bool = false, false + + if x { + fmt.Println("treated || of treatedBehaviour") + } else { + fmt.Println("control || of treatedBehaviour") + } + + fmt.Println("control && of treatedBehaviour") + fmt.Println("control && of || of treatedBehaviour") + fmt.Println("control && of && of treatedBehaviour") + fmt.Println("control && equals of treatedBehaviour") + fmt.Println("treated || equals of controlBehaviour") + + if y && x { + fmt.Println("treated && and && of controlBehaviour") + } else { + fmt.Println("control && and && of controlBehaviour") + } + + fmt.Println("treated || && || of controlBehaviour") + + y = false + y = x + y = x + + if y { + fmt.Println("y cleaned, so treated behaviour") + } else { + fmt.Println("y cleaned, so you see control behaviour") + } + + y = false + // This is done on purpose to check deep clean work + y = false + + fmt.Println("y not cleaned, so control behaviour") +} diff --git a/go/test/output/control/testSwitch.go b/go/test/output/control/testSwitch.go new file mode 100644 index 000000000..65d30d2a5 --- /dev/null +++ b/go/test/output/control/testSwitch.go @@ -0,0 +1,97 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testSwitch(ge GoExamples) { + fmt.Println("defaulter 1") + + switch os := ge.flagMthds.treatedBehaviour(newFlag); os { + case true: + fmt.Println("mike treat 2") + default: + fmt.Println("defaulter 2") + } + + fmt.Println("mike treat 3") + fmt.Println("mike treat 4") + + x := true + y := false + + fmt.Println("defaulter 5") + fmt.Println("mike control 6") + + switch os := true; x || y { + case true: + fmt.Println("mike treat 7") + default: + fmt.Println("mike control 7") + } + + print("treated") + x = true + fmt.Println("all are true") + + /* + If you are familiar with go progamming then you probably know that + this style of writing switch statments is like writing if-elseif-else + statements in C, C++, Java or Python. + + So, to refactor this code we will consider three cases: + (ith case statement means position of the case statement from first case) + + Case1: + If ith case statement evaluates to true and all case statements + above this statement evaluates to false. (This also includes if 1st case + statement evaluates to true). + Do: + Then we will remove whole switch statment and replace it with body + of ith case statment. + + Case2: + If ith case statement evaluates to true and all case statements + above this statement evaluates to isBot(it means cannot determine + whether it is true or false). + Do: + Then we will remove all the cases below the ith case statement and + rewrite the switch statement with ith case statment as default. (check + corresponding refactored output without -treated of this file in + 'output/control' directory.) + + Case3: + If ith case statment is false. + Do: + Then remove it from the switch statement in refactored output. + */ + x = true + y = false + + // Switch 1 + switch { + case x: + fmt.Println("switch test 1") + default: + fmt.Println("switch test 6") + } + + fmt.Println("switch test 13") + + // Switch 3 + switch { + case y && x: + fmt.Println("switch test 16") + } +} diff --git a/go/test/output/treated/deepClean.go b/go/test/output/treated/deepClean.go new file mode 100644 index 000000000..33fe7153d --- /dev/null +++ b/go/test/output/treated/deepClean.go @@ -0,0 +1,95 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +// A defer statement defers the execution of a function until the surrounding function returns. +func (ge GoExamples) useOfDefer() bool { + defer ge.storeuseInit() + return true +} + +func (ge GoExamples) storeuseBefore() { + /* + TODO: There is work going on to add the deep clean feature. + In this case the first if statment should be treated because + ge.basicFeature value may get affected by stale feature flag. + */ + if ge.basicFeature { + fmt.Println("Hi basicFeature") + } + if ge.localService { + fmt.Println("hi localService") + } + if ge.newFeatures { + fmt.Println("hi newFeatures") + } + + if !ge.localService { + fmt.Println("not localService") + } else { + fmt.Println("localService") + } + + if ge.localService && ge.newFeatures { + fmt.Println("localService and newFeatures") + } + + if ge.newFeatures { + fmt.Println("newFeatures") + } +} + +// This function is also acting as a pointer reciever +// Methods with pointer receivers can modify the value to which the receiver points +// This also using above two functions +func (ge *GoExamples) storeuseInit() { + ge.basicFeature = true + ge.localService = ge.flagMthds.controlBehaviour(localFlag) + ge.newFeatures = ge.flagMthds.treatedBehaviour(newFlag) + + pointerfieldX := true + pointerfieldY := &ge.localService + fmt.Println("I initialised basicFeature") + + if ge.localService { + fmt.Println("I initialised localService") + } + fmt.Println("pointers to be treated/not treated") +} + +func (ge GoExamples) storeuseAfter() { + fmt.Println("Hi basicFeature again") + if ge.localService { + fmt.Println("hi localService again") + } + if ge.newFeatures { + fmt.Println("hi newFeatures again") + } + + if !ge.localService { + fmt.Println("not localService again") + } else { + fmt.Println("localService again") + } + + if ge.localService && ge.newFeatures { + fmt.Println("localService and newFeatures again") + } + + if ge.newFeatures { + fmt.Println("newFeatures again") + } +} diff --git a/go/test/output/treated/init.go b/go/test/output/treated/init.go new file mode 100644 index 000000000..d8b4eaeb0 --- /dev/null +++ b/go/test/output/treated/init.go @@ -0,0 +1,56 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +// PropFlag :defining a type for flag +type PropFlag int + +// This contatins flags +// This works like enum in golang +// If we got any other implementation of flags then we will see on that in future +const ( + //comment0 + globalFlag PropFlag = iota //comment1 + //comment4 + localFlag + newFlag +) + +// FlagMethods : This will contains treatment and control methods +type FlagMethods struct { +} + +func (flgMthd FlagMethods) treatedBehaviour(flag PropFlag) bool { + return true +} +func (flgMthd FlagMethods) controlBehaviour(flag PropFlag) bool { + return true +} +func (flgMthd FlagMethods) commonBehaviour(str string, flag2 PropFlag) bool { + return true +} + +// GoExamples : This will act as a class +type GoExamples struct { + flagMthds FlagMethods + + localService, globalService, newFeatures, basicFeature bool +} + +func globalFeature(flag PropFlag) bool { + if flag == globalFlag { + return true + } + return false +} diff --git a/go/test/output/treated/testConditional.go b/go/test/output/treated/testConditional.go new file mode 100644 index 000000000..c24e0a4a9 --- /dev/null +++ b/go/test/output/treated/testConditional.go @@ -0,0 +1,80 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testIfConditionalAndInitExpressions(ge GoExamples) { + // Treated Control behaviour will be governed by three or more flags + if ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag) { + fmt.Println("treat1") + } else { + fmt.Println("control1") + } + + if globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag) { + fmt.Println("treat2") + } else { + fmt.Println("control2") + } + + if globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag) { + fmt.Println("treat3") + } else { + fmt.Println("control3") + } + + fmt.Println("treat1 with ||") + + if ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag) { + fmt.Println("treat4") + } else { + fmt.Println("control4") + } + + if globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag) { + fmt.Println("treat5") + } else { + fmt.Println("control5") + } + + if globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag) { + fmt.Println("treat6") + } else { + fmt.Println("control6") + } + + fmt.Println("control4 with &&") + + //comment1 + a := true //comment2 + //comment3 + b := ge.flagMthds.treatedBehaviour(newFlag) //comment4 + //comment5 + if b { + fmt.Println("treat4 on a && b") + } else { + fmt.Println("control4 on a && b") + } + + fmt.Println("treat5 on a || b") + + fmt.Println("treat6 with v") + + b = b && !b + fmt.Println("treat7 with v") + + fmt.Println("control8 with v") + +} diff --git a/go/test/output/treated/testExpressions.go b/go/test/output/treated/testExpressions.go new file mode 100644 index 000000000..632263e91 --- /dev/null +++ b/go/test/output/treated/testExpressions.go @@ -0,0 +1,83 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testExpressions(ge GoExamples) { + + fmt.Println("treated behaviour of treatedBehaviour") + + //global feature is not in properties right now. So this should not get treated + if globalFeature(staleFlag) { + fmt.Println("global treated behaviour") + } else { + fmt.Println("global control behaviour") + } + + fmt.Println("control behaviour of controlBehaviour") + + var x, y bool = false, false + + fmt.Println("treated || of treatedBehaviour") + + if x { + fmt.Println("treated && of treatedBehaviour") + } else { + fmt.Println("control && of treatedBehaviour") + } + + if x || y { + fmt.Println("treated && of || of treatedBehaviour") + } else { + fmt.Println("control && of || of treatedBehaviour") + } + + if x && y { + fmt.Println("treated && of && of treatedBehaviour") + } else { + fmt.Println("control && of && of treatedBehaviour") + } + + if y == x { + fmt.Println("treated && equals of treatedBehaviour") + } else { + fmt.Println("control && equals of treatedBehaviour") + } + + if y == x { + fmt.Println("treated || equals of controlBehaviour") + } else { + fmt.Println("control || equals of controlBehaviour") + } + + fmt.Println("control && and && of controlBehaviour") + + if y || x { + fmt.Println("treated || && || of controlBehaviour") + } else { + fmt.Println("control || && || of controlBehaviour") + } + + y = true + y = false + y = true + + fmt.Println("y cleaned, so treated behaviour") + y = true == x + // This is done on purpose to check deep clean work + y = true + fmt.Println("y not cleaned, so treated behaviour") + +} diff --git a/go/test/output/treated/testSwitch.go b/go/test/output/treated/testSwitch.go new file mode 100644 index 000000000..2fea4be5b --- /dev/null +++ b/go/test/output/treated/testSwitch.go @@ -0,0 +1,111 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package testfiles + +import "fmt" + +func testSwitch(ge GoExamples) { + + fmt.Println("mike treat 1") + + switch os := ge.flagMthds.treatedBehaviour(newFlag); os { + case true: + fmt.Println("mike treat 2") + default: + fmt.Println("defaulter 2") + } + + fmt.Println("defaulter 3") + + fmt.Println("defaulter 4") + + x := true + y := false + + switch os := (x || y); os { + case true: + fmt.Println("mike treat 5") + default: + fmt.Println("defaulter 5") + } + + switch os := true; x || y { + case true: + fmt.Println("mike treat 6") + default: + fmt.Println("mike control 6") + } + + fmt.Println("mike control 7") + + print("treated") + x = y + + fmt.Println("someone is false") + + /* + If you are familiar with go progamming then you probably know that + this style of writing switch statments is like writing if-elseif-else + statements in C, C++, Java or Python. + + So, to refactor this code we will consider three cases: + (ith case statement means position of the case statement from first case) + + Case1: + If ith case statement evaluates to true and all case statements + above this statement evaluates to false. (This also includes if 1st case + statement evaluates to true). + Do: + Then we will remove whole switch statment and replace it with body + of ith case statment. + + Case2: + If ith case statement evaluates to true and all case statements + above this statement evaluates to isBot(it means cannot determine + whether it is true or false). + Do: + Then we will remove all the cases below the ith case statement and + rewrite the switch statement with ith case statment as default. (check + corresponding refactored output without -treated of this file in + 'output/control' directory.) + + Case3: + If ith case statment is false. + Do: + Then remove it from the switch statement in refactored output. + */ + + x = true + y = false + + fmt.Println("switch test 1") + + // Switch 2 + switch { + case x: + fmt.Println("switch test 9") + case (x || y): + fmt.Println("switch test 10") + case (x && y): + fmt.Println("switch test 11") + case y == x: + fmt.Println("switch test 12") + x = y || ge.flagMthds.treatedBehaviour(newFlag) + case y == x: + fmt.Println("switch test 13") + case y || x: + fmt.Println("switch test 15") + } + +} diff --git a/go/test/piranha_test.go b/go/test/piranha_test.go new file mode 100644 index 000000000..3d8147836 --- /dev/null +++ b/go/test/piranha_test.go @@ -0,0 +1,146 @@ +/* +Copyright (c) 2021 Uber Technologies, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + +except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the + +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing permissions and +limitations under the License. +*/ +package main + +import ( + "bufio" + "fmt" + "log" + "os" + "testing" + + "github.com/PiranhaGo/src" +) + +// TestFiles :This will test the output from the correct output +func TestFiles(t *testing.T) { + tables := []struct { + input string + output string + }{ + {"./input/init.go", "./output/control/init.go"}, + {"./input/testExpressions.go", "./output/control/testExpressions.go"}, + {"./input/testConditional.go", "./output/control/testConditional.go"}, + {"./input/testSwitch.go", "./output/control/testSwitch.go"}, + {"./input/deepClean.go", "./output/control/deepClean.go"}, + + {"./input/init.go", "./output/treated/init.go"}, + {"./input/testExpressions.go", "./output/treated/testExpressions.go"}, + {"./input/testConditional.go", "./output/treated/testConditional.go"}, + {"./input/testSwitch.go", "./output/treated/testSwitch.go"}, + {"./input/deepClean.go", "./output/treated/deepClean.go"}, + } + // running each files as like they are running with this command + // For one Pass + // ../piranha -p ../properties.json -s "{filename}" -f staleFlag -o ./treatedFiles/$(basename {filename}) -treated + var argsOnePass []string + argsOnePass = append(argsOnePass, "-p") + argsOnePass = append(argsOnePass, "../properties.json") + argsOnePass = append(argsOnePass, "-s") + argsOnePass = append(argsOnePass, "{filename}") + argsOnePass = append(argsOnePass, "-f") + argsOnePass = append(argsOnePass, "staleFlag") + argsOnePass = append(argsOnePass, "-o") + argsOnePass = append(argsOnePass, "{filename}") + + fmt.Print("Output format: \n") + fmt.Print("Line : \n") + fmt.Print("Line : \n") + fmt.Print("\n") + fmt.Print("Starting Tests \n") + for ind, table := range tables { + if ind == 5 { + argsOnePass = append(argsOnePass, "-treated") + } + argsOnePass[3] = table.input + argsOnePass[7] = "temp.go" + src.RunPiranha(argsOnePass) + + fmt.Print("Testing ") + if ind < 5 { + fmt.Print("without -treated\n") + } else { + fmt.Print("with -treated\n") + } + fmt.Print("Matching with: ") + fmt.Println(table.output) + FileNotMatched := false + corrFile, err := os.Open(table.output) + if err != nil { + fmt.Println("File reading error of correct file", err) + return + } + treatFile, err := os.Open("temp.go") + if err != nil { + fmt.Println("File reading error of treat file", err) + return + } + + corrScan := bufio.NewScanner(corrFile) + treatScan := bufio.NewScanner(treatFile) + + lineNumcorrFile := 0 + lineNumtreatFile := 0 + + endOfcorrFile := false + endOftreatFile := false + for corrScan.Scan() { + // Scanning + treatScan.Scan() + lineNumcorrFile++ + lineNumtreatFile++ + for corrScan.Text() == "" { + if !corrScan.Scan() { + endOfcorrFile = true + break + } + lineNumcorrFile++ + } + for treatScan.Text() == "" { + if !treatScan.Scan() { + endOftreatFile = true + break + } + lineNumtreatFile++ + } + if endOfcorrFile || endOftreatFile { + break + } + + // Matching + if corrScan.Text() != treatScan.Text() { + fmt.Print("\n") + fmt.Print("Line ", lineNumcorrFile, ": ", corrScan.Text()) + fmt.Print("\n") + fmt.Print("Line ", lineNumtreatFile, ": ", treatScan.Text()) + fmt.Print("\n") + FileNotMatched = true + break + } + if FileNotMatched { + break + } + } + if FileNotMatched { + t.Errorf("Files didn't matched, see above output") + } else { + fmt.Println("File Matched Sucessfully") + } + fmt.Println() + del := os.Remove("temp.go") + if del != nil { + log.Fatal(del) + } + } +} From 7ac72d1f9a6b0f3bf68c69ebd294b8b5a9b6cfec Mon Sep 17 00:00:00 2001 From: crekIron Date: Tue, 30 Mar 2021 22:52:41 +0530 Subject: [PATCH 2/9] added link of go readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ae0ce5f4a..4027d79f2 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ This repository contains four independent versions of Piranha, one for each of t To use/build each version, look under the corresponding [lang]/ directory and follow instructions in the corresponding [lang]/README.md file. Make sure to cd into that directory to build any related code following the instructions in the README. +- [PiranhaGo](go/README.md) - [PiranhaJava](java/README.md) - [PiranhaJS](javascript/README.md) - [PiranhaObjC](objc/README.md) From 36445bf84ed0269830d099d3a36b93859f225de5 Mon Sep 17 00:00:00 2001 From: crekIron Date: Tue, 1 Jun 2021 19:27:43 +0530 Subject: [PATCH 3/9] changes in readme and test file --- go/README.md | 2 +- go/test/piranha_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go/README.md b/go/README.md index b3aaf43dc..ccb2f55ad 100644 --- a/go/README.md +++ b/go/README.md @@ -16,4 +16,4 @@ Optional arguments: otherwise it is control. -o OUTPUT: Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place. ``` -3. To do a test run, run piranha on `example/testExample.go`. Run `./piranha -p properties.json -s ./example/testExample.go -o ./example/treatedExample.go -f staleFlag` command in root directory. You will get your refracted file as `/example/treatedExample.go`. \ No newline at end of file +3. To do a test run, run piranha on `example/testExample.go`. Run `./piranha -p properties.json -s ./example/testExample.go -o ./example/treatedExample.go -f staleFlag` command in root directory. You will get your refactored file as `/example/treatedExample.go`. \ No newline at end of file diff --git a/go/test/piranha_test.go b/go/test/piranha_test.go index 3d8147836..5368f7379 100644 --- a/go/test/piranha_test.go +++ b/go/test/piranha_test.go @@ -41,7 +41,7 @@ func TestFiles(t *testing.T) { {"./input/testSwitch.go", "./output/treated/testSwitch.go"}, {"./input/deepClean.go", "./output/treated/deepClean.go"}, } - // running each files as like they are running with this command + // running each file as if they are running with this command // For one Pass // ../piranha -p ../properties.json -s "{filename}" -f staleFlag -o ./treatedFiles/$(basename {filename}) -treated var argsOnePass []string @@ -133,7 +133,7 @@ func TestFiles(t *testing.T) { } } if FileNotMatched { - t.Errorf("Files didn't matched, see above output") + t.Errorf("Files didn't match, see above output") } else { fmt.Println("File Matched Sucessfully") } From 38274f78fa652e1c0970d0acf9a5268234bb9e09 Mon Sep 17 00:00:00 2001 From: crekIron Date: Sun, 25 Jul 2021 15:40:49 +0530 Subject: [PATCH 4/9] Some changes done. --- go/README.md | 12 +- go/example/testExample.go | 32 ++-- go/example/treatedExample.go | 20 +-- go/properties.json | 3 +- go/src/piranha.go | 26 ++-- go/test/input/deepClean.go | 34 ++--- go/test/input/testConditional.go | 52 +++---- go/test/input/testExpressions.go | 48 +++--- go/test/input/testSwitch.go | 68 ++++----- go/test/output/control/deepClean.go | 30 ++-- go/test/output/control/testConditional.go | 33 ++-- go/test/output/control/testExpressions.go | 30 ++-- go/test/output/control/testSwitch.go | 31 ++-- go/test/output/treated/deepClean.go | 36 ++--- go/test/output/treated/testConditional.go | 44 +++--- go/test/output/treated/testExpressions.go | 39 +++-- go/test/output/treated/testSwitch.go | 42 +++--- go/test/piranha_test.go | 174 ++++++++++++---------- 18 files changed, 386 insertions(+), 368 deletions(-) diff --git a/go/README.md b/go/README.md index ccb2f55ad..00f79a55f 100644 --- a/go/README.md +++ b/go/README.md @@ -5,15 +5,15 @@ Instructions:- 2. Below are the instructions for running for the single file. ``` Inputs from args -Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG [-treated] [-o OUTPUT] +Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG -mode MODE_NAME [-o OUTPUT] Required arguments: - -s SOURCE_FILE: Path of the file to be refactored + -s SOURCE_FILE: Path of the file to be refactored. -p PROPERTIES: Configuration file (json format) for Piranha. - -f STALE_FLAG: Name of the stale flag + -f STALE_FLAG: Name of the stale flag. + -mode MODE_NAME: If MODE_NAME=treated, then flag is treated, + otherwise MODE_NAME=control, it is control. Optional arguments: -h: Show the options and exit. - -treated: If this is given, then flag is treated, - otherwise it is control. -o OUTPUT: Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place. ``` -3. To do a test run, run piranha on `example/testExample.go`. Run `./piranha -p properties.json -s ./example/testExample.go -o ./example/treatedExample.go -f staleFlag` command in root directory. You will get your refactored file as `/example/treatedExample.go`. \ No newline at end of file +3. To do a test run, run piranha on `example/testExample.go`. Run `./piranha -p properties.json -s ./example/testExample.go -o ./example/treatedExample.go -f staleFlag -mode control` command in root directory. You will get your refactored file as `/example/treatedExample.go`. diff --git a/go/example/testExample.go b/go/example/testExample.go index 3102ffbad..ea7447660 100644 --- a/go/example/testExample.go +++ b/go/example/testExample.go @@ -19,51 +19,51 @@ func testExpressions(ge GoExamples) { var x, y bool = false, false if ge.flagMthds.treatedBehaviour(staleFlag) || x { - fmt.Println("treated || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } else { - fmt.Println("control || of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } if ge.flagMthds.treatedBehaviour(staleFlag) && x { - fmt.Println("treated && of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") } else { - fmt.Println("control && of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") } if ge.flagMthds.treatedBehaviour(staleFlag) && (x || y) { - fmt.Println("treated && of || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") } else { - fmt.Println("control && of || of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") } if ge.flagMthds.treatedBehaviour(staleFlag) && (x && y) { - fmt.Println("treated && of && of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") } else { - fmt.Println("control && of && of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") } if ge.flagMthds.treatedBehaviour(staleFlag) && y == x { - fmt.Println("treated && equals of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") } else { - fmt.Println("control && equals of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") } if ge.flagMthds.controlBehaviour(staleFlag) || y == x { - fmt.Println("treated || equals of controlBehaviour") + fmt.Println("then-braanch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") } else { - fmt.Println("control || equals of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") } if ge.flagMthds.controlBehaviour(staleFlag) && y && x { - fmt.Println("treated && and && of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } else { - fmt.Println("control && and && of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } if ge.flagMthds.controlBehaviour(staleFlag) || y || x { - fmt.Println("treated || && || of controlBehaviour") + fmt.Println("then-braanch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } else { - fmt.Println("control || && || of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } } diff --git a/go/example/treatedExample.go b/go/example/treatedExample.go index f37c1953f..87c49533a 100644 --- a/go/example/treatedExample.go +++ b/go/example/treatedExample.go @@ -19,22 +19,22 @@ func testExpressions(ge GoExamples) { var x, y bool = false, false if x { - fmt.Println("treated || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } else { - fmt.Println("control || of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } - fmt.Println("control && of treatedBehaviour") - fmt.Println("control && of || of treatedBehaviour") - fmt.Println("control && of && of treatedBehaviour") - fmt.Println("control && equals of treatedBehaviour") - fmt.Println("treated || equals of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") + fmt.Println("then-braanch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") if y && x { - fmt.Println("treated && and && of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } else { - fmt.Println("control && and && of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } - fmt.Println("treated || && || of controlBehaviour") + fmt.Println("then-braanch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } diff --git a/go/properties.json b/go/properties.json index 44414b07b..8e2490a77 100644 --- a/go/properties.json +++ b/go/properties.json @@ -16,4 +16,5 @@ "argumentIndex": 1 } ] - } \ No newline at end of file + } + \ No newline at end of file diff --git a/go/src/piranha.go b/go/src/piranha.go index 6b09c90ce..9379340c1 100644 --- a/go/src/piranha.go +++ b/go/src/piranha.go @@ -27,36 +27,36 @@ import ( /* Inputs from args -Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG [-treated] [-o OUTPUT] +Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG -mode MODE_NAME [-o OUTPUT] Required arguments: - -s SOURCE_FILE: Path of the file to be refactored + -s SOURCE_FILE: Path of the file to be refactored. -p PROPERTIES: Configuration file (json format) for Piranha. - -f STALE_FLAG: Name of the stale flag + -f STALE_FLAG: Name of the stale flag. + -mode MODE_NAME: If MODE_NAME=treated, then flag is treated, + otherwise MODE_NAME=control, it is control. Optional arguments: -h: Show the options and exit. - -treated: If this is given, then flag is treated, - otherwise it is control. -o OUTPUT: Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place. */ func help() { //Help message fmt.Println( - "Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG [-treated] [-o OUTPUT]", + "Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG -mode MODE_NAME [-o OUTPUT]", "\nRequired arguments:", "\n\t\t\t-s SOURCE_FILE: Path of the file to be refactored.", "\n\t\t\t-p PROPERTIES: Configuration file (json format) for Piranha.", "\n\t\t\t-f STALE_FLAG: Name of the stale flag.", + "\n\t\t\t-mode MODE_NAME: If MODE_NAME=treated, then flag is treated,", + "\n\t\t\totherwise MODE_NAME=control, it is control.", "\nOptional arguments:", "\n\t\t\t-h: Show the options and exit.", - "\n\t\t\t-treated: If this is given, then flag is treated,", - "\n\t\t\totherwise it is control.", "\n\t\t\t-o OUTPUT: Destination of the refactored output from piranha.", "\n\t\t\tIf -o is not provided, then the source file is updated in place.") } // RunPiranha : the main function for the piranha tool func RunPiranha(inArgs []string) { - var sourceFile, configFile, flagName, outputFileName string = "", "", "", "" + var sourceFile, configFile, flagName, outputFileName string var isTreated = false sizeOfArgs := len(inArgs) if len(inArgs) < 2 { @@ -86,8 +86,12 @@ func RunPiranha(inArgs []string) { if index+1 < sizeOfArgs { flagName = inArgs[index+1] } - case "-treated": - isTreated = true + case "-mode": + if index+1 < sizeOfArgs { + if inArgs[index+1] == "treated" { + isTreated = true + } + } case "-o": if index+1 < sizeOfArgs { outputFileName = inArgs[index+1] diff --git a/go/test/input/deepClean.go b/go/test/input/deepClean.go index f04ca65d4..1904a20e9 100644 --- a/go/test/input/deepClean.go +++ b/go/test/input/deepClean.go @@ -28,27 +28,27 @@ func (ge GoExamples) storeuseBefore() { ge.basicFeature value may get affected by stale feature flag. */ if ge.basicFeature { - fmt.Println("Hi basicFeature") + fmt.Println("then-branch of `ge.basicFeature`") } if ge.localService { - fmt.Println("hi localService") + fmt.Println("then-branch of `ge.localService`") } if ge.newFeatures { - fmt.Println("hi newFeatures") + fmt.Println("then-branch of `ge.newFeatures`") } if !ge.localService { - fmt.Println("not localService") + fmt.Println("then-branch of `!ge.localService`") } else { - fmt.Println("localService") + fmt.Println("else-branch of `!ge.localService`") } if ge.localService && ge.newFeatures { - fmt.Println("localService and newFeatures") + fmt.Println("then-branch of `ge.localService && ge.newFeatures`") } if ge.newFeatures { - fmt.Println("newFeatures") + fmt.Println("then-branch of `ge.newFeatures`") } } @@ -64,42 +64,42 @@ func (ge *GoExamples) storeuseInit() { pointerfieldY := &ge.localService if ge.basicFeature { - fmt.Println("I initialised basicFeature") + fmt.Println("then-branch of `ge.basicFeature`") } if ge.localService { - fmt.Println("I initialised localService") + fmt.Println("then-branch of `ge.localService`") } //testing pointer. I think need more test cases like this if *pointerfieldX || !*pointerfieldY { - fmt.Println("pointers to be treated/not treated") + fmt.Println("then-branch of `*pointerfieldX || !*pointerfieldY`") } } func (ge GoExamples) storeuseAfter() { // I love basicFeature if ge.basicFeature { - fmt.Println("Hi basicFeature again") + fmt.Println("then-branch of `ge.basicFeature`") } if ge.localService { - fmt.Println("hi localService again") + fmt.Println("then-branch of `ge.localService`") } if ge.newFeatures { - fmt.Println("hi newFeatures again") + fmt.Println("then-branch of `ge.newFeatures`") } if !ge.localService { - fmt.Println("not localService again") + fmt.Println("then-branch of `!ge.localService`") } else { - fmt.Println("localService again") + fmt.Println("else-branch of `!ge.localService`") } if ge.localService && ge.newFeatures { - fmt.Println("localService and newFeatures again") + fmt.Println("then-branch of `ge.localService && ge.newFeatures`") } if ge.newFeatures { - fmt.Println("newFeatures again") + fmt.Println("then-branch of `ge.newFeatures`") } } diff --git a/go/test/input/testConditional.go b/go/test/input/testConditional.go index d36b2cc25..99843a939 100644 --- a/go/test/input/testConditional.go +++ b/go/test/input/testConditional.go @@ -18,51 +18,51 @@ import "fmt" func testIfConditionalAndInitExpressions(ge GoExamples) { // Treated Control behaviour will be governed by three or more flags if ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag) { - fmt.Println("treat1") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag)`") } else { - fmt.Println("control1") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag)`") } if ge.flagMthds.treatedBehaviour(staleFlag) && globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag) { - fmt.Println("treat2") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } else { - fmt.Println("control2") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } if globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) { - fmt.Println("treat3") + fmt.Println("then-branch of `globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } else { - fmt.Println("control3") + fmt.Println("else-branch of `globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } if ge.flagMthds.treatedBehaviour(staleFlag) || ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag) { - fmt.Println("treat1 with ||") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag)`") } else { - fmt.Println("control1 with ||") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag)`") } if ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag) { - fmt.Println("treat4") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag)`") } else { - fmt.Println("control4") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag)`") } if ge.flagMthds.controlBehaviour(staleFlag) || globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag) { - fmt.Println("treat5") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } else { - fmt.Println("control5") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } if globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) { - fmt.Println("treat6") + fmt.Println("then-branch of `globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } else { - fmt.Println("control6") + fmt.Println("else-branch of `globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } if ge.flagMthds.controlBehaviour(staleFlag) && ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag) { - fmt.Println("treat4 with &&") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) && ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag)`") } else { - fmt.Println("control4 with &&") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag)`") } //comment1 @@ -71,33 +71,33 @@ func testIfConditionalAndInitExpressions(ge GoExamples) { b := ge.flagMthds.treatedBehaviour(newFlag) //comment4 //comment5 if a && b { - fmt.Println("treat4 on a && b") + fmt.Println("then-branch of `a && b`") } else { - fmt.Println("control4 on a && b") + fmt.Println("else-branch of `a && b`") } if a || b { - fmt.Println("treat5 on a || b") + fmt.Println("then-branch of `a || b`") } else { - fmt.Println("control5 on a || b") + fmt.Println("else-branch of `a || b`") } if v := ge.flagMthds.treatedBehaviour(staleFlag); v { - fmt.Println("treat6 with v") + fmt.Println("then-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v`") } else { - fmt.Println("control6 with v") + fmt.Println("else-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v`") } if v := ge.flagMthds.treatedBehaviour(staleFlag); v == true { b = a && b && !b - fmt.Println("treat7 with v") + fmt.Println("then-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v == true`") } else { - fmt.Println("control7 with v") + fmt.Println("else-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v == true`") } if v := ge.flagMthds.treatedBehaviour(staleFlag); v != true { - fmt.Println("treat8 with v") + fmt.Println("then-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v != true`") } else { - fmt.Println("control8 with v") + fmt.Println("else-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v != true`") } } diff --git a/go/test/input/testExpressions.go b/go/test/input/testExpressions.go index 919276a9f..d52cb9ee1 100644 --- a/go/test/input/testExpressions.go +++ b/go/test/input/testExpressions.go @@ -17,9 +17,9 @@ import "fmt" func testExpressions(ge GoExamples) { if ge.flagMthds.treatedBehaviour(staleFlag) { - fmt.Println("treated behaviour of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag)`") } else { - fmt.Println("control behaviour of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag)`") } //global feature is not in properties right now. So this should not get treated @@ -30,58 +30,58 @@ func testExpressions(ge GoExamples) { } if ge.flagMthds.controlBehaviour(staleFlag) { - fmt.Println("treated behaviour of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag)`") } else { - fmt.Println("control behaviour of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag)`") } var x, y bool = false, false if ge.flagMthds.treatedBehaviour(staleFlag) || x { - fmt.Println("treated || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } else { - fmt.Println("control || of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } if ge.flagMthds.treatedBehaviour(staleFlag) && x { - fmt.Println("treated && of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") } else { - fmt.Println("control && of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") } if ge.flagMthds.treatedBehaviour(staleFlag) && (x || y) { - fmt.Println("treated && of || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") } else { - fmt.Println("control && of || of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") } if ge.flagMthds.treatedBehaviour(staleFlag) && (x && y) { - fmt.Println("treated && of && of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") } else { - fmt.Println("control && of && of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") } if ge.flagMthds.treatedBehaviour(staleFlag) && y == x { - fmt.Println("treated && equals of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") } else { - fmt.Println("control && equals of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") } if ge.flagMthds.controlBehaviour(staleFlag) || y == x { - fmt.Println("treated || equals of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") } else { - fmt.Println("control || equals of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") } if ge.flagMthds.controlBehaviour(staleFlag) && y && x { - fmt.Println("treated && and && of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } else { - fmt.Println("control && and && of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } if ge.flagMthds.controlBehaviour(staleFlag) || y || x { - fmt.Println("treated || && || of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } else { - fmt.Println("control || && || of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } y = ge.flagMthds.treatedBehaviour(staleFlag) @@ -89,9 +89,9 @@ func testExpressions(ge GoExamples) { y = ge.flagMthds.treatedBehaviour(staleFlag) || x if y { - fmt.Println("y cleaned, so treated behaviour") + fmt.Println("y cleaned, so then-branch of y") } else { - fmt.Println("y cleaned, so you see control behaviour") + fmt.Println("y cleaned, so else-branch of y") } y = ge.flagMthds.treatedBehaviour(staleFlag) && y == x @@ -99,9 +99,9 @@ func testExpressions(ge GoExamples) { y = ge.flagMthds.treatedBehaviour(staleFlag) if y { - fmt.Println("y not cleaned, so treated behaviour") + fmt.Println("y not cleaned, so then-branch of y") } else { - fmt.Println("y not cleaned, so control behaviour") + fmt.Println("y not cleaned, so else-branch of y") } } diff --git a/go/test/input/testSwitch.go b/go/test/input/testSwitch.go index ad33a9af5..d49c4d819 100644 --- a/go/test/input/testSwitch.go +++ b/go/test/input/testSwitch.go @@ -18,30 +18,30 @@ import "fmt" func testSwitch(ge GoExamples) { switch os := ge.flagMthds.treatedBehaviour(staleFlag); os { case true: - fmt.Println("mike treat 1") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os`") default: - fmt.Println("defaulter 1") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os`") } switch os := ge.flagMthds.treatedBehaviour(newFlag); os { case true: - fmt.Println("mike treat 2") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(newFlag); os`") default: - fmt.Println("defaulter 2") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(newFlag); os`") } switch !ge.flagMthds.treatedBehaviour(staleFlag) { case true: - fmt.Println("mike treat 3") + fmt.Println("1st case of `!ge.flagMthds.treatedBehaviour(staleFlag)`") default: - fmt.Println("defaulter 3") + fmt.Println("default case of `!ge.flagMthds.treatedBehaviour(staleFlag)`") } switch os := ge.flagMthds.controlBehaviour(staleFlag); os { case true: - fmt.Println("mike treat 4") + fmt.Println("1st case of `os := ge.flagMthds.controlBehaviour(staleFlag); os`") default: - fmt.Println("defaulter 4") + fmt.Println("default case of `os := ge.flagMthds.controlBehaviour(staleFlag); os`") } x := true @@ -49,39 +49,39 @@ func testSwitch(ge GoExamples) { switch os := ge.flagMthds.treatedBehaviour(staleFlag) && (x || y); os { case true: - fmt.Println("mike treat 5") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(staleFlag) && (x || y); os`") default: - fmt.Println("defaulter 5") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag) && (x || y); os`") } switch os := ge.flagMthds.treatedBehaviour(staleFlag); os && (x || y) { case true: - fmt.Println("mike treat 6") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os && (x || y)`") default: - fmt.Println("mike control 6") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os && (x || y)`") } switch os := ge.flagMthds.controlBehaviour(staleFlag); os && (x || y) { case true: - fmt.Println("mike treat 7") + fmt.Println("1st case of `os := ge.flagMthds.controlBehaviour(staleFlag); os && (x || y)`") default: - fmt.Println("mike control 7") + fmt.Println("default case of `os := ge.flagMthds.controlBehaviour(staleFlag); os && (x || y)`") } switch ge.flagMthds.treatedBehaviour(staleFlag) || x || y { case true: - print("treated") + print("1st case of `ge.flagMthds.treatedBehaviour(staleFlag) || x || y`") x = !ge.flagMthds.treatedBehaviour(staleFlag) || y case false: - print("control") + print("default case of `ge.flagMthds.treatedBehaviour(staleFlag) || x || y`") y = !ge.flagMthds.treatedBehaviour(staleFlag) || x } switch ge.flagMthds.controlBehaviour(staleFlag) && x && y { case true: - fmt.Println("all are true") + fmt.Println("1st case of `ge.flagMthds.controlBehaviour(staleFlag) && x && y`") case false: - fmt.Println("someone is false") + fmt.Println("default case of `ge.flagMthds.controlBehaviour(staleFlag) && x && y`") } /* @@ -122,46 +122,46 @@ func testSwitch(ge GoExamples) { // Switch 1 switch { case ge.flagMthds.treatedBehaviour(staleFlag) || x: - fmt.Println("switch test 1") + fmt.Println("switch 1 test `ge.flagMthds.treatedBehaviour(staleFlag) || x`") case ge.flagMthds.treatedBehaviour(staleFlag) && x: - fmt.Println("switch test 2") + fmt.Println("switch 1 test `ge.flagMthds.treatedBehaviour(staleFlag) && x`") case ge.flagMthds.treatedBehaviour(staleFlag) && (x || y): - fmt.Println("switch test 3") + fmt.Println("switch 1 test `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") case ge.flagMthds.treatedBehaviour(staleFlag) && (x && y): - fmt.Println("switch test 4") + fmt.Println("switch 1 test `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") case ge.flagMthds.treatedBehaviour(staleFlag) && y == x: - fmt.Println("switch test 5") + fmt.Println("switch 1 test `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") x = y || ge.flagMthds.treatedBehaviour(newFlag) case ge.flagMthds.controlBehaviour(staleFlag) || y == x: - fmt.Println("switch test 6") + fmt.Println("switch 1 test `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") case ge.flagMthds.controlBehaviour(staleFlag) && y && x: - fmt.Println("switch test 7") + fmt.Println("switch 1 test `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") case ge.flagMthds.controlBehaviour(staleFlag) || y || x: - fmt.Println("switch test 8") + fmt.Println("switch 1 test `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } // Switch 2 switch { case ge.flagMthds.treatedBehaviour(staleFlag) && x: - fmt.Println("switch test 9") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && x`") case ge.flagMthds.treatedBehaviour(staleFlag) && (x || y): - fmt.Println("switch test 10") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") case ge.flagMthds.treatedBehaviour(staleFlag) && (x && y): - fmt.Println("switch test 11") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") case ge.flagMthds.treatedBehaviour(staleFlag) && y == x: - fmt.Println("switch test 12") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") x = y || ge.flagMthds.treatedBehaviour(newFlag) case ge.flagMthds.controlBehaviour(staleFlag) || y == x: - fmt.Println("switch test 13") + fmt.Println("switch 2 test `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") case ge.flagMthds.controlBehaviour(staleFlag) && y && x: - fmt.Println("switch test 14") + fmt.Println("switch 2 test `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") case ge.flagMthds.controlBehaviour(staleFlag) || y || x: - fmt.Println("switch test 15") + fmt.Println("switch 2 test `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } // Switch 3 switch { case ge.flagMthds.controlBehaviour(staleFlag) && y && x: - fmt.Println("switch test 16") + fmt.Println("switch 3 `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } } diff --git a/go/test/output/control/deepClean.go b/go/test/output/control/deepClean.go index 6fbd7469a..b3900f26d 100644 --- a/go/test/output/control/deepClean.go +++ b/go/test/output/control/deepClean.go @@ -28,27 +28,27 @@ func (ge GoExamples) storeuseBefore() { ge.basicFeature value may get affected by stale feature flag. */ if ge.basicFeature { - fmt.Println("Hi basicFeature") + fmt.Println("then-branch of `ge.basicFeature`") } if ge.localService { - fmt.Println("hi localService") + fmt.Println("then-branch of `ge.localService`") } if ge.newFeatures { - fmt.Println("hi newFeatures") + fmt.Println("then-branch of `ge.newFeatures`") } if !ge.localService { - fmt.Println("not localService") + fmt.Println("then-branch of `!ge.localService`") } else { - fmt.Println("localService") + fmt.Println("else-branch of `!ge.localService`") } if ge.localService && ge.newFeatures { - fmt.Println("localService and newFeatures") + fmt.Println("then-branch of `ge.localService && ge.newFeatures`") } if ge.newFeatures { - fmt.Println("newFeatures") + fmt.Println("then-branch of `ge.newFeatures`") } } @@ -64,34 +64,34 @@ func (ge *GoExamples) storeuseInit() { pointerfieldY := &ge.localService if ge.localService { - fmt.Println("I initialised localService") + fmt.Println("then-branch of `ge.localService`") } //testing pointer. I think need more test cases like this if !*pointerfieldY { - fmt.Println("pointers to be treated/not treated") + fmt.Println("then-branch of `*pointerfieldX || !*pointerfieldY`") } } func (ge GoExamples) storeuseAfter() { if ge.localService { - fmt.Println("hi localService again") + fmt.Println("then-branch of `ge.localService`") } if ge.newFeatures { - fmt.Println("hi newFeatures again") + fmt.Println("then-branch of `ge.newFeatures`") } if !ge.localService { - fmt.Println("not localService again") + fmt.Println("then-branch of `!ge.localService`") } else { - fmt.Println("localService again") + fmt.Println("else-branch of `!ge.localService`") } if ge.localService && ge.newFeatures { - fmt.Println("localService and newFeatures again") + fmt.Println("then-branch of `ge.localService && ge.newFeatures`") } if ge.newFeatures { - fmt.Println("newFeatures again") + fmt.Println("then-branch of `ge.newFeatures`") } } diff --git a/go/test/output/control/testConditional.go b/go/test/output/control/testConditional.go index a575f2dec..29d537eec 100644 --- a/go/test/output/control/testConditional.go +++ b/go/test/output/control/testConditional.go @@ -16,38 +16,39 @@ package testfiles import "fmt" func testIfConditionalAndInitExpressions(ge GoExamples) { - fmt.Println("control1") - fmt.Println("control2") - fmt.Println("control3") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag)`") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") + fmt.Println("else-branch of `globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") if ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag) { - fmt.Println("treat1 with ||") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag)`") } else { - fmt.Println("control1 with ||") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag)`") } - fmt.Println("treat4") - fmt.Println("treat5") - fmt.Println("treat6") + + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag)`") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag)`") + fmt.Println("then-branch of `globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag)`") if ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag) { - fmt.Println("treat4 with &&") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) && ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag)`") } else { - fmt.Println("control4 with &&") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag)`") } //comment1 a := false //comment2 //comment3 b := ge.flagMthds.treatedBehaviour(newFlag) //comment4 - fmt.Println("control4 on a && b") + fmt.Println("else-branch of `a && b`") if b { - fmt.Println("treat5 on a || b") + fmt.Println("then-branch of `a || b`") } else { - fmt.Println("control5 on a || b") + fmt.Println("else-branch of `a || b`") } - fmt.Println("control6 with v") - fmt.Println("control7 with v") - fmt.Println("treat8 with v") + fmt.Println("else-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v`") + fmt.Println("else-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v == true`") + fmt.Println("then-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v != true`") } diff --git a/go/test/output/control/testExpressions.go b/go/test/output/control/testExpressions.go index efdbad6c8..d65fb9207 100644 --- a/go/test/output/control/testExpressions.go +++ b/go/test/output/control/testExpressions.go @@ -16,7 +16,7 @@ package testfiles import "fmt" func testExpressions(ge GoExamples) { - fmt.Println("control behaviour of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag)`") //global feature is not in properties right now. So this should not get treated if globalFeature(staleFlag) { @@ -25,42 +25,42 @@ func testExpressions(ge GoExamples) { fmt.Println("global control behaviour") } - fmt.Println("treated behaviour of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag)`") var x, y bool = false, false if x { - fmt.Println("treated || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } else { - fmt.Println("control || of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } - fmt.Println("control && of treatedBehaviour") - fmt.Println("control && of || of treatedBehaviour") - fmt.Println("control && of && of treatedBehaviour") - fmt.Println("control && equals of treatedBehaviour") - fmt.Println("treated || equals of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") if y && x { - fmt.Println("treated && and && of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } else { - fmt.Println("control && and && of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } - fmt.Println("treated || && || of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") y = false y = x y = x if y { - fmt.Println("y cleaned, so treated behaviour") + fmt.Println("y cleaned, so then-branch of y") } else { - fmt.Println("y cleaned, so you see control behaviour") + fmt.Println("y cleaned, so else-branch of y") } y = false // This is done on purpose to check deep clean work y = false - fmt.Println("y not cleaned, so control behaviour") + fmt.Println("y not cleaned, so else-branch of y") } diff --git a/go/test/output/control/testSwitch.go b/go/test/output/control/testSwitch.go index 65d30d2a5..bb5589946 100644 --- a/go/test/output/control/testSwitch.go +++ b/go/test/output/control/testSwitch.go @@ -16,34 +16,34 @@ package testfiles import "fmt" func testSwitch(ge GoExamples) { - fmt.Println("defaulter 1") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os`") switch os := ge.flagMthds.treatedBehaviour(newFlag); os { case true: - fmt.Println("mike treat 2") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(newFlag); os`") default: - fmt.Println("defaulter 2") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(newFlag); os`") } - fmt.Println("mike treat 3") - fmt.Println("mike treat 4") + fmt.Println("1st case of `!ge.flagMthds.treatedBehaviour(staleFlag)`") + fmt.Println("1st case of `os := ge.flagMthds.controlBehaviour(staleFlag); os`") x := true y := false - fmt.Println("defaulter 5") - fmt.Println("mike control 6") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag) && (x || y); os`") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os && (x || y)`") switch os := true; x || y { case true: - fmt.Println("mike treat 7") + fmt.Println("1st case of `os := ge.flagMthds.controlBehaviour(staleFlag); os && (x || y)`") default: - fmt.Println("mike control 7") + fmt.Println("default case of `os := ge.flagMthds.controlBehaviour(staleFlag); os && (x || y)`") } - print("treated") + print("1st case of `ge.flagMthds.treatedBehaviour(staleFlag) || x || y`") x = true - fmt.Println("all are true") + fmt.Println("1st case of `ge.flagMthds.controlBehaviour(staleFlag) && x && y`") /* If you are familiar with go progamming then you probably know that @@ -76,22 +76,23 @@ func testSwitch(ge GoExamples) { Do: Then remove it from the switch statement in refactored output. */ + x = true y = false // Switch 1 switch { case x: - fmt.Println("switch test 1") + fmt.Println("switch 1 test `ge.flagMthds.treatedBehaviour(staleFlag) || x`") default: - fmt.Println("switch test 6") + fmt.Println("switch 1 test `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") } - fmt.Println("switch test 13") + fmt.Println("switch 2 test `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") // Switch 3 switch { case y && x: - fmt.Println("switch test 16") + fmt.Println("switch 3 `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } } diff --git a/go/test/output/treated/deepClean.go b/go/test/output/treated/deepClean.go index 33fe7153d..ca6b29a55 100644 --- a/go/test/output/treated/deepClean.go +++ b/go/test/output/treated/deepClean.go @@ -28,27 +28,27 @@ func (ge GoExamples) storeuseBefore() { ge.basicFeature value may get affected by stale feature flag. */ if ge.basicFeature { - fmt.Println("Hi basicFeature") + fmt.Println("then-branch of `ge.basicFeature`") } if ge.localService { - fmt.Println("hi localService") + fmt.Println("then-branch of `ge.localService`") } if ge.newFeatures { - fmt.Println("hi newFeatures") + fmt.Println("then-branch of `ge.newFeatures`") } if !ge.localService { - fmt.Println("not localService") + fmt.Println("then-branch of `!ge.localService`") } else { - fmt.Println("localService") + fmt.Println("else-branch of `!ge.localService`") } if ge.localService && ge.newFeatures { - fmt.Println("localService and newFeatures") + fmt.Println("then-branch of `ge.localService && ge.newFeatures`") } if ge.newFeatures { - fmt.Println("newFeatures") + fmt.Println("then-branch of `ge.newFeatures`") } } @@ -62,34 +62,36 @@ func (ge *GoExamples) storeuseInit() { pointerfieldX := true pointerfieldY := &ge.localService - fmt.Println("I initialised basicFeature") + + fmt.Println("then-branch of `ge.basicFeature`") if ge.localService { - fmt.Println("I initialised localService") + fmt.Println("then-branch of `ge.localService`") } - fmt.Println("pointers to be treated/not treated") + + fmt.Println("then-branch of `*pointerfieldX || !*pointerfieldY`") } func (ge GoExamples) storeuseAfter() { - fmt.Println("Hi basicFeature again") + fmt.Println("then-branch of `ge.basicFeature`") if ge.localService { - fmt.Println("hi localService again") + fmt.Println("then-branch of `ge.localService`") } if ge.newFeatures { - fmt.Println("hi newFeatures again") + fmt.Println("then-branch of `ge.newFeatures`") } if !ge.localService { - fmt.Println("not localService again") + fmt.Println("then-branch of `!ge.localService`") } else { - fmt.Println("localService again") + fmt.Println("else-branch of `!ge.localService`") } if ge.localService && ge.newFeatures { - fmt.Println("localService and newFeatures again") + fmt.Println("then-branch of `ge.localService && ge.newFeatures`") } if ge.newFeatures { - fmt.Println("newFeatures again") + fmt.Println("then-branch of `ge.newFeatures`") } } diff --git a/go/test/output/treated/testConditional.go b/go/test/output/treated/testConditional.go index c24e0a4a9..baac8312a 100644 --- a/go/test/output/treated/testConditional.go +++ b/go/test/output/treated/testConditional.go @@ -18,44 +18,44 @@ import "fmt" func testIfConditionalAndInitExpressions(ge GoExamples) { // Treated Control behaviour will be governed by three or more flags if ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag) { - fmt.Println("treat1") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag)`") } else { - fmt.Println("control1") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag) && globalFeature(globalFlag)`") } if globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag) { - fmt.Println("treat2") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } else { - fmt.Println("control2") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } if globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(localFlag) { - fmt.Println("treat3") + fmt.Println("then-branch of `globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } else { - fmt.Println("control3") + fmt.Println("else-branch of `globalFeature(globalFlag) && ge.flagMthds.treatedBehaviour(staleFlag) && ge.flagMthds.treatedBehaviour(localFlag)`") } - fmt.Println("treat1 with ||") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || ge.flagMthds.treatedBehaviour(localFlag) || globalFeature(globalFlag)`") if ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag) { - fmt.Println("treat4") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag)`") } else { - fmt.Println("control4") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag) || globalFeature(globalFlag)`") } if globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag) { - fmt.Println("treat5") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } else { - fmt.Println("control5") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } if globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(localFlag) { - fmt.Println("treat6") + fmt.Println("then-branch of `globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } else { - fmt.Println("control6") + fmt.Println("else-branch of `globalFeature(globalFlag) || ge.flagMthds.controlBehaviour(staleFlag) || ge.flagMthds.controlBehaviour(localFlag)`") } - fmt.Println("control4 with &&") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && ge.flagMthds.controlBehaviour(localFlag) && globalFeature(globalFlag)`") //comment1 a := true //comment2 @@ -63,18 +63,14 @@ func testIfConditionalAndInitExpressions(ge GoExamples) { b := ge.flagMthds.treatedBehaviour(newFlag) //comment4 //comment5 if b { - fmt.Println("treat4 on a && b") + fmt.Println("then-branch of `a && b`") } else { - fmt.Println("control4 on a && b") + fmt.Println("else-branch of `a && b`") } - fmt.Println("treat5 on a || b") - - fmt.Println("treat6 with v") - + fmt.Println("then-branch of `a || b`") + fmt.Println("then-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v`") b = b && !b - fmt.Println("treat7 with v") - - fmt.Println("control8 with v") - + fmt.Println("then-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v == true`") + fmt.Println("else-branch of `v := ge.flagMthds.treatedBehaviour(staleFlag); v != true`") } diff --git a/go/test/output/treated/testExpressions.go b/go/test/output/treated/testExpressions.go index 632263e91..1e168302c 100644 --- a/go/test/output/treated/testExpressions.go +++ b/go/test/output/treated/testExpressions.go @@ -16,8 +16,7 @@ package testfiles import "fmt" func testExpressions(ge GoExamples) { - - fmt.Println("treated behaviour of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag)`") //global feature is not in properties right now. So this should not get treated if globalFeature(staleFlag) { @@ -26,58 +25,58 @@ func testExpressions(ge GoExamples) { fmt.Println("global control behaviour") } - fmt.Println("control behaviour of controlBehaviour") - + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag)`") var x, y bool = false, false - fmt.Println("treated || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") if x { - fmt.Println("treated && of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") } else { - fmt.Println("control && of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") } if x || y { - fmt.Println("treated && of || of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") } else { - fmt.Println("control && of || of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") } if x && y { - fmt.Println("treated && of && of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") } else { - fmt.Println("control && of && of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") } if y == x { - fmt.Println("treated && equals of treatedBehaviour") + fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") } else { - fmt.Println("control && equals of treatedBehaviour") + fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") } if y == x { - fmt.Println("treated || equals of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") } else { - fmt.Println("control || equals of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") } - fmt.Println("control && and && of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") if y || x { - fmt.Println("treated || && || of controlBehaviour") + fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } else { - fmt.Println("control || && || of controlBehaviour") + fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } y = true y = false y = true - fmt.Println("y cleaned, so treated behaviour") + fmt.Println("y cleaned, so then-branch of y") + y = true == x // This is done on purpose to check deep clean work y = true - fmt.Println("y not cleaned, so treated behaviour") + fmt.Println("y not cleaned, so then-branch of y") } diff --git a/go/test/output/treated/testSwitch.go b/go/test/output/treated/testSwitch.go index 2fea4be5b..1bb8a6f49 100644 --- a/go/test/output/treated/testSwitch.go +++ b/go/test/output/treated/testSwitch.go @@ -16,43 +16,39 @@ package testfiles import "fmt" func testSwitch(ge GoExamples) { - - fmt.Println("mike treat 1") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os`") switch os := ge.flagMthds.treatedBehaviour(newFlag); os { case true: - fmt.Println("mike treat 2") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(newFlag); os`") default: - fmt.Println("defaulter 2") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(newFlag); os`") } - fmt.Println("defaulter 3") - - fmt.Println("defaulter 4") + fmt.Println("default case of `!ge.flagMthds.treatedBehaviour(staleFlag)`") + fmt.Println("default case of `os := ge.flagMthds.controlBehaviour(staleFlag); os`") x := true y := false switch os := (x || y); os { case true: - fmt.Println("mike treat 5") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(staleFlag) && (x || y); os`") default: - fmt.Println("defaulter 5") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag) && (x || y); os`") } switch os := true; x || y { case true: - fmt.Println("mike treat 6") + fmt.Println("1st case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os && (x || y)`") default: - fmt.Println("mike control 6") + fmt.Println("default case of `os := ge.flagMthds.treatedBehaviour(staleFlag); os && (x || y)`") } - fmt.Println("mike control 7") - - print("treated") + fmt.Println("default case of `os := ge.flagMthds.controlBehaviour(staleFlag); os && (x || y)`") + print("1st case of `ge.flagMthds.treatedBehaviour(staleFlag) || x || y`") x = y - - fmt.Println("someone is false") + fmt.Println("default case of `ge.flagMthds.controlBehaviour(staleFlag) && x && y`") /* If you are familiar with go progamming then you probably know that @@ -89,23 +85,23 @@ func testSwitch(ge GoExamples) { x = true y = false - fmt.Println("switch test 1") + fmt.Println("switch 1 test `ge.flagMthds.treatedBehaviour(staleFlag) || x`") // Switch 2 switch { case x: - fmt.Println("switch test 9") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && x`") case (x || y): - fmt.Println("switch test 10") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") case (x && y): - fmt.Println("switch test 11") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") case y == x: - fmt.Println("switch test 12") + fmt.Println("switch 2 test `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") x = y || ge.flagMthds.treatedBehaviour(newFlag) case y == x: - fmt.Println("switch test 13") + fmt.Println("switch 2 test `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") case y || x: - fmt.Println("switch test 15") + fmt.Println("switch 2 test `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } } diff --git a/go/test/piranha_test.go b/go/test/piranha_test.go index 5368f7379..9119c5cd4 100644 --- a/go/test/piranha_test.go +++ b/go/test/piranha_test.go @@ -23,23 +23,79 @@ import ( "github.com/PiranhaGo/src" ) +func compFiles(file1 string, file2 string) bool { + FileNotMatched := false + corrFile, err := os.Open(file2) + if err != nil { + fmt.Println("File reading error of correct file", err) + return false + } + treatFile, err := os.Open(file1) + if err != nil { + fmt.Println("File reading error of treat file", err) + return false + } + + corrScan := bufio.NewScanner(corrFile) + treatScan := bufio.NewScanner(treatFile) + + lineNumcorrFile := 0 + lineNumtreatFile := 0 + + endOfcorrFile := false + endOftreatFile := false + for corrScan.Scan() { + // Scanning + treatScan.Scan() + lineNumcorrFile++ + lineNumtreatFile++ + for corrScan.Text() == "" { + if !corrScan.Scan() { + endOfcorrFile = true + break + } + lineNumcorrFile++ + } + for treatScan.Text() == "" { + if !treatScan.Scan() { + endOftreatFile = true + break + } + lineNumtreatFile++ + } + if endOfcorrFile || endOftreatFile { + break + } + + // Matching + if corrScan.Text() != treatScan.Text() { + fmt.Print("\n") + fmt.Print("Line ", lineNumcorrFile, ": ", corrScan.Text()) + fmt.Print("\n") + fmt.Print("Line ", lineNumtreatFile, ": ", treatScan.Text()) + fmt.Print("\n") + FileNotMatched = true + break + } + if FileNotMatched { + break + } + } + return FileNotMatched +} + // TestFiles :This will test the output from the correct output func TestFiles(t *testing.T) { tables := []struct { - input string - output string + input string + outputControl string + outputTreated string }{ - {"./input/init.go", "./output/control/init.go"}, - {"./input/testExpressions.go", "./output/control/testExpressions.go"}, - {"./input/testConditional.go", "./output/control/testConditional.go"}, - {"./input/testSwitch.go", "./output/control/testSwitch.go"}, - {"./input/deepClean.go", "./output/control/deepClean.go"}, - - {"./input/init.go", "./output/treated/init.go"}, - {"./input/testExpressions.go", "./output/treated/testExpressions.go"}, - {"./input/testConditional.go", "./output/treated/testConditional.go"}, - {"./input/testSwitch.go", "./output/treated/testSwitch.go"}, - {"./input/deepClean.go", "./output/treated/deepClean.go"}, + {"./input/init.go", "./output/control/init.go", "./output/treated/init.go"}, + {"./input/testExpressions.go", "./output/control/testExpressions.go", "./output/treated/testExpressions.go"}, + {"./input/testConditional.go", "./output/control/testConditional.go", "./output/treated/testConditional.go"}, + {"./input/testSwitch.go", "./output/control/testSwitch.go", "./output/treated/testSwitch.go"}, + {"./input/deepClean.go", "./output/control/deepClean.go", "./output/treated/deepClean.go"}, } // running each file as if they are running with this command // For one Pass @@ -53,85 +109,47 @@ func TestFiles(t *testing.T) { argsOnePass = append(argsOnePass, "staleFlag") argsOnePass = append(argsOnePass, "-o") argsOnePass = append(argsOnePass, "{filename}") + argsOnePass = append(argsOnePass, "-mode") + argsOnePass = append(argsOnePass, "{MODE_NAME}") fmt.Print("Output format: \n") fmt.Print("Line : \n") fmt.Print("Line : \n") fmt.Print("\n") fmt.Print("Starting Tests \n") - for ind, table := range tables { - if ind == 5 { - argsOnePass = append(argsOnePass, "-treated") - } + + fmt.Print("Testing with -mode treated\n\n") + var FileNotMatched bool + for _, table := range tables { argsOnePass[3] = table.input argsOnePass[7] = "temp.go" + argsOnePass[9] = "treated" + fmt.Print("Matching with: ") + fmt.Println(table.outputTreated) src.RunPiranha(argsOnePass) - fmt.Print("Testing ") - if ind < 5 { - fmt.Print("without -treated\n") + FileNotMatched = compFiles("temp.go", table.outputTreated) + if FileNotMatched { + t.Errorf("Files didn't match, see above output") } else { - fmt.Print("with -treated\n") - } - fmt.Print("Matching with: ") - fmt.Println(table.output) - FileNotMatched := false - corrFile, err := os.Open(table.output) - if err != nil { - fmt.Println("File reading error of correct file", err) - return + fmt.Println("File Matched Sucessfully") } - treatFile, err := os.Open("temp.go") - if err != nil { - fmt.Println("File reading error of treat file", err) - return + fmt.Println() + del := os.Remove("temp.go") + if del != nil { + log.Fatal(del) } + } + fmt.Print("Testing with -mode control\n") + for _, table := range tables { + argsOnePass[3] = table.input + argsOnePass[7] = "temp.go" + argsOnePass[9] = "control" + fmt.Print("Matching with: ") + fmt.Println(table.outputControl) + src.RunPiranha(argsOnePass) - corrScan := bufio.NewScanner(corrFile) - treatScan := bufio.NewScanner(treatFile) - - lineNumcorrFile := 0 - lineNumtreatFile := 0 - - endOfcorrFile := false - endOftreatFile := false - for corrScan.Scan() { - // Scanning - treatScan.Scan() - lineNumcorrFile++ - lineNumtreatFile++ - for corrScan.Text() == "" { - if !corrScan.Scan() { - endOfcorrFile = true - break - } - lineNumcorrFile++ - } - for treatScan.Text() == "" { - if !treatScan.Scan() { - endOftreatFile = true - break - } - lineNumtreatFile++ - } - if endOfcorrFile || endOftreatFile { - break - } - - // Matching - if corrScan.Text() != treatScan.Text() { - fmt.Print("\n") - fmt.Print("Line ", lineNumcorrFile, ": ", corrScan.Text()) - fmt.Print("\n") - fmt.Print("Line ", lineNumtreatFile, ": ", treatScan.Text()) - fmt.Print("\n") - FileNotMatched = true - break - } - if FileNotMatched { - break - } - } + FileNotMatched = compFiles("temp.go", table.outputControl) if FileNotMatched { t.Errorf("Files didn't match, see above output") } else { From 47b1f0e974ff7ce214853931d501c3580e0627f8 Mon Sep 17 00:00:00 2001 From: crekIron Date: Mon, 2 Aug 2021 22:44:49 +0530 Subject: [PATCH 5/9] Used flag package to parse the arguments. --- go/main.go | 24 +++++++++++- go/src/piranha.go | 86 +++++++++++------------------------------ go/test/piranha_test.go | 26 ++++--------- 3 files changed, 51 insertions(+), 85 deletions(-) diff --git a/go/main.go b/go/main.go index 523c9daf0..a09401bb0 100644 --- a/go/main.go +++ b/go/main.go @@ -14,11 +14,31 @@ limitations under the License. package main import ( - "os" + "flag" "github.com/PiranhaGo/src" ) func main() { - src.RunPiranha(os.Args) + var sourceFile, configFile, flagName, outputFileName, modeName string + var isTreated = false + + // get configFile + flag.StringVar(&configFile, "p", "PROPERTIES", "Configuration file (json format) for Piranha.") + // get sourceFile + flag.StringVar(&sourceFile, "s", "SOURCE_FILE", "Path of the file to be refactored.") + // get flagName + flag.StringVar(&flagName, "f", "STALE_FLAG", "Name of the stale flag.") + // check treatedMode + flag.StringVar(&modeName, "mode", "MODE_NAME", "If MODE_NAME=treated, then flag is treated, otherwise MODE_NAME=control, it is control.") + if modeName == "treated" { + isTreated = true + } + // get outputFileName + flag.StringVar(&outputFileName, "o", "OUTPUT", "Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place.") + + flag.Parse() + + + src.RunPiranha(sourceFile, configFile, flagName, outputFileName, isTreated) } diff --git a/go/src/piranha.go b/go/src/piranha.go index 9379340c1..0cfc6ae9f 100644 --- a/go/src/piranha.go +++ b/go/src/piranha.go @@ -38,83 +38,41 @@ Optional arguments: -h: Show the options and exit. -o OUTPUT: Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place. */ -func help() { - //Help message - fmt.Println( - "Usage: ./piranha [-h] -p PROPERTIES -s SOURCE_FILE -f STALE_FLAG -mode MODE_NAME [-o OUTPUT]", - "\nRequired arguments:", - "\n\t\t\t-s SOURCE_FILE: Path of the file to be refactored.", - "\n\t\t\t-p PROPERTIES: Configuration file (json format) for Piranha.", - "\n\t\t\t-f STALE_FLAG: Name of the stale flag.", - "\n\t\t\t-mode MODE_NAME: If MODE_NAME=treated, then flag is treated,", - "\n\t\t\totherwise MODE_NAME=control, it is control.", - "\nOptional arguments:", - "\n\t\t\t-h: Show the options and exit.", - "\n\t\t\t-o OUTPUT: Destination of the refactored output from piranha.", - "\n\t\t\tIf -o is not provided, then the source file is updated in place.") +func reportArgumentError(arg string) { + if arg == "configFile" { + fmt.Println("Please provide configuration file of json format.") + } else if arg == "sourceFile" { + fmt.Println("Please provide source file of go format.") + } + fmt.Println("For more info, run ./piranha -h.") } // RunPiranha : the main function for the piranha tool -func RunPiranha(inArgs []string) { - var sourceFile, configFile, flagName, outputFileName string - var isTreated = false - sizeOfArgs := len(inArgs) - if len(inArgs) < 2 { - help() - return - } - for index, arg := range inArgs { - switch arg { - case "-h": - help() - return - case "-p": - if index+1 < sizeOfArgs { - configFile = inArgs[index+1] - if !strings.HasSuffix(configFile, ".json") { - return - } - } - case "-s": - if index+1 < sizeOfArgs { - sourceFile = inArgs[index+1] - if !strings.HasSuffix(sourceFile, ".go") { - return - } - } - case "-f": - if index+1 < sizeOfArgs { - flagName = inArgs[index+1] - } - case "-mode": - if index+1 < sizeOfArgs { - if inArgs[index+1] == "treated" { - isTreated = true - } - } - case "-o": - if index+1 < sizeOfArgs { - outputFileName = inArgs[index+1] - } - default: - break - } - } - - if flagName == "" { +func RunPiranha(sourceFile string, configFile string, flagName string, outputFileName string, isTreated bool) { + if flagName == "STALE_FLAG" { fmt.Println("Please provide a flag.") } - if sourceFile == "" { + if sourceFile == "SOURCE_FILE" { fmt.Println("Please provide a source file that is to be refactored.") } - if configFile == "" { + if configFile == "PROPERTIES" { fmt.Println("Please provide a config file. See README for more instructions.") } - if flagName == "" || sourceFile == "" || configFile == "" { + if flagName == "STALE_FLAG" || sourceFile == "SOURCE_FILE" || configFile == "PROPERTIES" { fmt.Println("For more info, run ./piranha -h.") return } + if !strings.HasSuffix(configFile, ".json") { + reportArgumentError("configFile") + return + } + + if !strings.HasSuffix(sourceFile, ".go") { + reportArgumentError("sourceFile") + return + } + fs := token.NewFileSet() parsed, err := decorator.ParseFile(fs, sourceFile, nil, parser.ParseComments) if err != nil { diff --git a/go/test/piranha_test.go b/go/test/piranha_test.go index 9119c5cd4..e7993cef0 100644 --- a/go/test/piranha_test.go +++ b/go/test/piranha_test.go @@ -100,17 +100,9 @@ func TestFiles(t *testing.T) { // running each file as if they are running with this command // For one Pass // ../piranha -p ../properties.json -s "{filename}" -f staleFlag -o ./treatedFiles/$(basename {filename}) -treated - var argsOnePass []string - argsOnePass = append(argsOnePass, "-p") - argsOnePass = append(argsOnePass, "../properties.json") - argsOnePass = append(argsOnePass, "-s") - argsOnePass = append(argsOnePass, "{filename}") - argsOnePass = append(argsOnePass, "-f") - argsOnePass = append(argsOnePass, "staleFlag") - argsOnePass = append(argsOnePass, "-o") - argsOnePass = append(argsOnePass, "{filename}") - argsOnePass = append(argsOnePass, "-mode") - argsOnePass = append(argsOnePass, "{MODE_NAME}") + var configFile = "../properties.json" + var flagName = "staleFlag" + var isTreated bool fmt.Print("Output format: \n") fmt.Print("Line : \n") @@ -119,14 +111,12 @@ func TestFiles(t *testing.T) { fmt.Print("Starting Tests \n") fmt.Print("Testing with -mode treated\n\n") + isTreated = true var FileNotMatched bool for _, table := range tables { - argsOnePass[3] = table.input - argsOnePass[7] = "temp.go" - argsOnePass[9] = "treated" fmt.Print("Matching with: ") fmt.Println(table.outputTreated) - src.RunPiranha(argsOnePass) + src.RunPiranha(table.input, configFile, flagName, "temp.go", isTreated) FileNotMatched = compFiles("temp.go", table.outputTreated) if FileNotMatched { @@ -141,13 +131,11 @@ func TestFiles(t *testing.T) { } } fmt.Print("Testing with -mode control\n") + isTreated=false for _, table := range tables { - argsOnePass[3] = table.input - argsOnePass[7] = "temp.go" - argsOnePass[9] = "control" fmt.Print("Matching with: ") fmt.Println(table.outputControl) - src.RunPiranha(argsOnePass) + src.RunPiranha(table.input, configFile, flagName, "temp.go", isTreated) FileNotMatched = compFiles("temp.go", table.outputControl) if FileNotMatched { From 38680bd24eea88b13235c8b33e2b68d2bcc2fcc2 Mon Sep 17 00:00:00 2001 From: Harshcs517 Date: Fri, 6 Aug 2021 21:58:24 +0530 Subject: [PATCH 6/9] Changes made in src/piranha.go --- go/src/piranha.go | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/go/src/piranha.go b/go/src/piranha.go index 0cfc6ae9f..851e7083c 100644 --- a/go/src/piranha.go +++ b/go/src/piranha.go @@ -39,10 +39,17 @@ Optional arguments: -o OUTPUT: Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place. */ func reportArgumentError(arg string) { - if arg == "configFile" { + switch arg { + case "configFileSuffix": fmt.Println("Please provide configuration file of json format.") - } else if arg == "sourceFile" { + case "sourceFileSuffix": fmt.Println("Please provide source file of go format.") + case "flagName": + fmt.Println("Please provide a flag.") + case "configFile": + fmt.Println("Please provide a config file. See README for more instructions.") + case "sourceFile": + fmt.Println("Please provide a source file that is to be refactored.") } fmt.Println("For more info, run ./piranha -h.") } @@ -50,26 +57,25 @@ func reportArgumentError(arg string) { // RunPiranha : the main function for the piranha tool func RunPiranha(sourceFile string, configFile string, flagName string, outputFileName string, isTreated bool) { if flagName == "STALE_FLAG" { - fmt.Println("Please provide a flag.") + reportArgumentError("flagName") + return } if sourceFile == "SOURCE_FILE" { - fmt.Println("Please provide a source file that is to be refactored.") + reportArgumentError("sourceFile") + return } if configFile == "PROPERTIES" { - fmt.Println("Please provide a config file. See README for more instructions.") - } - if flagName == "STALE_FLAG" || sourceFile == "SOURCE_FILE" || configFile == "PROPERTIES" { - fmt.Println("For more info, run ./piranha -h.") + reportArgumentError("configFile") return } if !strings.HasSuffix(configFile, ".json") { - reportArgumentError("configFile") + reportArgumentError("sourceFileSuffix") return } if !strings.HasSuffix(sourceFile, ".go") { - reportArgumentError("sourceFile") + reportArgumentError("sourceFileSuffix") return } @@ -82,17 +88,13 @@ func RunPiranha(sourceFile string, configFile string, flagName string, outputFil var cleaner staleFlagCleaner cleaner.init(configFile, flagName, isTreated) newRoot := cleaner.run(parsed) - //////////////////////// - // For debugging purpose. It prints out the ast. - // spew.Dump(newRoot) - /////////////////////// if outputFileName == "" { outputFileName = sourceFile } - outputFile, err := os.Create(outputFileName) + outputFile, _ := os.Create(outputFileName) /* - Here we are typecasting newRoot to dst.File.It is safe because the root of AST + Here we are typecasting newRoot to dst.File. It is safe because the root of AST always starts with the dst.File type. */ decorator.Fprint(outputFile, newRoot.(*dst.File)) From b37339ec98932a897a4bb0764c271a78946fa373 Mon Sep 17 00:00:00 2001 From: Harshcs517 Date: Fri, 6 Aug 2021 22:23:48 +0530 Subject: [PATCH 7/9] Incoperated 30% of comments in src/staleFlagCleaner.go --- go/src/staleFlagCleaner.go | 115 +++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 63 deletions(-) diff --git a/go/src/staleFlagCleaner.go b/go/src/staleFlagCleaner.go index 19a3f88cd..b2eec6731 100644 --- a/go/src/staleFlagCleaner.go +++ b/go/src/staleFlagCleaner.go @@ -22,69 +22,64 @@ import ( /* We have used dst package instead of official go ast package because ast package - does not keep positions of comment in place. So, we use dst package which keeps - the positions of comment in place. It is similiar to ast package and have same - functions as ast. So you can use documentation of ast to see the details of helper - functions. + does not keep positions of comments, we use dst package which keeps the positions + of comment in place. It is similiar to the ast package and have same functions as ast. + So you can use documentation of ast to see the details of helper functions. */ "github.com/dave/dst" "github.com/dave/dst/dstutil" ) -// API : For the type of API +// API describes the type of API. type API int const ( - isTreated API = iota - isControl - isTesting - isUnknown + _isTreated API = iota + _isControl + _isTesting + _isUnknown ) -// Methods : For json it is +// Methods describes the parent field of the json format. type Methods struct { Methods []FlagAPI `json:"methodProperties"` } -// FlagAPI : for getting the type from config file +// FlagAPI denotes the field values in json format. type FlagAPI struct { MethodName string `json:"methodName"` OfType string `json:"flagType"` FlagIndex int `json:"argumentIndex"` } -// Value : This is made to not confuse with true and false in code +// Value is made to not confuse with true and false in code. type Value int const ( isTrue Value = iota isFalse - // This will be returned when you don't have to find true or false - isBot + // This will be returned when you don't have to find true or false. + isUndefined ) -// Operator : To get the boolean operators -type Operator int - -const ( - and Operator = iota - or - not +// Some useful global variables +var ( + treated = "treated" + control = "control" +) +var ( + strTrue = "true" + strFalse = "false" ) - -// Some useful global variable -var treated, control string = "treated", "control" -var strTrue, strFalse string = "true", "false" // Implementing this as whole class type staleFlagCleaner struct { configFile string - FlagAPIArr []FlagAPI methods Methods /* - Here valueMap contains those which came from the stale function output. - It means that this will used for cleaning in Deep Clean Pass + Here valueMap contains those variable names whose value are affected by the stale function output. + It means that this will used for cleaning in Deep Clean Pass. */ valueMap map[string]Value functype map[string]FlagAPI @@ -108,7 +103,7 @@ func (sfc *staleFlagCleaner) ParseJSON() { jsonFile, err := os.Open(sfc.configFile) if err != nil { - log.Fatalf("failed opening file: %s", err) + log.Fatalf("failed opening file: %v", err) os.Exit(-1) } @@ -152,15 +147,15 @@ func (sfc *staleFlagCleaner) flagTypeAPI(callExpr *dst.CallExpr) API { if element.FlagIndex == flagIndex { switch element.OfType { case treated: - return isTreated + return _isTreated case control: - return isControl + return _isControl default: - return isUnknown + return _isUnknown } } } - return isUnknown + return _isUnknown } /* This function will evaluate all expression nodes here */ @@ -183,13 +178,13 @@ func (sfc *staleFlagCleaner) evaluateExprNode(exprNode dst.Expr) Value { // Get the type of API typeOfAPI := sfc.flagTypeAPI(exprUnderConsideration) // Hardcoding the output of some API types - if typeOfAPI == isTreated { + if typeOfAPI == _isTreated { if sfc.isTreated { return isTrue } return isFalse } - if typeOfAPI == isControl { + if typeOfAPI == _isControl { if sfc.isTreated { return isFalse } @@ -199,7 +194,7 @@ func (sfc *staleFlagCleaner) evaluateExprNode(exprNode dst.Expr) Value { case *dst.BinaryExpr: valX := sfc.evaluateExprNode(exprUnderConsideration.X) valY := sfc.evaluateExprNode(exprUnderConsideration.Y) - if valX != isBot || valY != isBot { + if valX != isUndefined || valY != isUndefined { switch exprUnderConsideration.Op { case token.LAND: //stands for && if valX == isFalse || valY == isFalse { @@ -216,7 +211,7 @@ func (sfc *staleFlagCleaner) evaluateExprNode(exprNode dst.Expr) Value { return isFalse } case token.EQL: - if valX != isBot && valY != isBot { + if valX != isUndefined && valY != isUndefined { if valX == valY { return isTrue } @@ -268,7 +263,7 @@ func (sfc *staleFlagCleaner) evaluateExprNode(exprNode dst.Expr) Value { //Do nothing for now } - return isBot + return isUndefined } // This is the pre function of the dstutil.Apply @@ -297,7 +292,7 @@ func (sfc *staleFlagCleaner) checkForBoolLiterals(value dst.Expr) bool { /* Below function have this aim: -If Value is isBot or it is a bool literal, then we are not adding that to valueMap +If Value is isUndefined or it is a bool literal, then we are not adding that to valueMap if not then will add to valueMap. This signifies whether variable has effect of flag or not. */ @@ -306,7 +301,7 @@ func (sfc *staleFlagCleaner) updateValueMapPost(name dst.Expr, value dst.Expr) { doNotDelLiterals := sfc.checkForBoolLiterals(value) switch d := name.(type) { case *dst.Ident: - if valOfExpr == isBot || doNotDelLiterals { + if valOfExpr == isUndefined || doNotDelLiterals { if _, ok := sfc.valueMap[d.Name]; ok { delete(sfc.valueMap, d.Name) } @@ -316,7 +311,7 @@ func (sfc *staleFlagCleaner) updateValueMapPost(name dst.Expr, value dst.Expr) { case *dst.SelectorExpr: switch ident := d.X.(type) { case *dst.Ident: - if valOfExpr == isBot || doNotDelLiterals { + if valOfExpr == isUndefined || doNotDelLiterals { if _, ok := sfc.valueMap[ident.Name+"."+d.Sel.Name]; ok { delete(sfc.valueMap, ident.Name+"."+d.Sel.Name) } @@ -336,7 +331,7 @@ It will deal with *dst.ValueSpec. Values of variable stored in valueMap will be deleted from node. */ func (sfc *staleFlagCleaner) DelValStmt(names *[]*dst.Ident, values *[]dst.Expr) bool { - valOfExpr := isBot + valOfExpr := isUndefined delCallExpr := false doNotDelLiterals := false for ind := 0; ind < len((*names)); ind++ { @@ -348,7 +343,7 @@ func (sfc *staleFlagCleaner) DelValStmt(names *[]*dst.Ident, values *[]dst.Expr) sfc.updateValueMapPost((*names)[ind], (*values)[ind]) } - if (valOfExpr != isBot && !doNotDelLiterals) || (*names)[ind].Name == sfc.flagName || delCallExpr { + if (valOfExpr != isUndefined && !doNotDelLiterals) || (*names)[ind].Name == sfc.flagName || delCallExpr { if len((*values)) != 0 { var trueIdent dst.Ident if valOfExpr == isTrue { @@ -362,12 +357,9 @@ func (sfc *staleFlagCleaner) DelValStmt(names *[]*dst.Ident, values *[]dst.Expr) return true } } - valOfExpr = isBot + valOfExpr = isUndefined } - if len((*names)) == 0 { - return true - } - return false + return len((*names)) == 0 } /* @@ -375,7 +367,7 @@ It will deal with *dst.AssignStmt. Values of variable stored in valueMap will be deleted from node. */ func (sfc *staleFlagCleaner) DelAssStmt(names *[]dst.Expr, values *[]dst.Expr) bool { - valOfExpr := isBot + valOfExpr := isUndefined delCallExpr := false doNotDelLiterals := false for ind := 0; ind < len((*names)); ind++ { @@ -388,7 +380,7 @@ func (sfc *staleFlagCleaner) DelAssStmt(names *[]dst.Expr, values *[]dst.Expr) b // Need to see what to do with this thing sfc.updateValueMapPost((*names)[ind], (*values)[ind]) - if (valOfExpr != isBot && !doNotDelLiterals) || delCallExpr { + if (valOfExpr != isUndefined && !doNotDelLiterals) || delCallExpr { var trueIdent dst.Ident if valOfExpr == isTrue { trueIdent.Name = strTrue @@ -401,10 +393,7 @@ func (sfc *staleFlagCleaner) DelAssStmt(names *[]dst.Expr, values *[]dst.Expr) b } } } - if len((*names)) == 0 { - return true - } - return false + return len((*names)) == 0 } // This is the post function of the dstutil.Apply @@ -453,7 +442,7 @@ func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { // Init of Ifstmt will get handled in assignStmt // Now evaluate the cond. Cond is already refactored due to pre-order traversal. cond := sfc.evaluateExprNode(d.Cond) - if cond != isBot { + if cond != isUndefined { if cond == isFalse { if d.Else != nil { for _, a := range d.Else.(*dst.BlockStmt).List { @@ -472,7 +461,7 @@ func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { // Init of switchstmt will get handled in assignStmt if d.Tag != nil { valExpr := sfc.evaluateExprNode(d.Tag) - if valExpr != isBot { + if valExpr != isUndefined { notfoundCase := false for _, exprstmt := range d.Body.List { if exprstmt.(*dst.CaseClause).List != nil { //nil means default case @@ -502,15 +491,15 @@ func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { } else { //now switch is like elseif statements so do accordingly needDeletion := false - isBotAbove := false + isUndefinedAbove := false for ind := 0; ind < len(d.Body.List); ind++ { exprstmt := d.Body.List[ind] if exprstmt.(*dst.CaseClause).List != nil { valCaseClause := sfc.evaluateExprNode(exprstmt.(*dst.CaseClause).List[0]) if valCaseClause == isTrue { //this has to go out as switch is going to delete - //On the condition that there was no expression above whose value is isBot. - if !isBotAbove { + //On the condition that there was no expression above whose value is isUndefined. + if !isUndefinedAbove { for _, bodyEle := range exprstmt.(*dst.CaseClause).Body { n.InsertBefore(bodyEle) } @@ -534,7 +523,7 @@ func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { } } else { // so now value is bot - isBotAbove = true + isUndefinedAbove = true } } } @@ -546,8 +535,8 @@ func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { case *dst.BinaryExpr: valX := sfc.evaluateExprNode(d.X) valY := sfc.evaluateExprNode(d.Y) - if valX == isBot || valY == isBot { - if valX == isBot && valY == isBot { + if valX == isUndefined || valY == isUndefined { + if valX == isUndefined && valY == isUndefined { //do nothing } else { //now one of them is not bot @@ -568,7 +557,7 @@ func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { newNode := n.Node() var trueIdent dst.Ident // either valX is not bot or valY. both cannot be bot at the same time as we checked out above - if valX != isBot { + if valX != isUndefined { if valX == isTrue { trueIdent.Name = strTrue } else { From 6ff77de6fc92506b2dbae53c4abd5fdb08cdb74a Mon Sep 17 00:00:00 2001 From: Harshcs517 Date: Sat, 7 Aug 2021 16:44:26 +0530 Subject: [PATCH 8/9] Incoperated 70% of comments in src/staleFlagCleaner.go --- go/src/piranha.go | 6 ++- go/src/staleFlagCleaner.go | 77 ++++++++++++++++++---------------- go/test/input/init.go | 3 +- go/test/output/control/init.go | 3 +- go/test/output/treated/init.go | 3 +- go/test/piranha_test.go | 2 + 6 files changed, 52 insertions(+), 42 deletions(-) diff --git a/go/src/piranha.go b/go/src/piranha.go index 851e7083c..0c76f28a3 100644 --- a/go/src/piranha.go +++ b/go/src/piranha.go @@ -86,7 +86,11 @@ func RunPiranha(sourceFile string, configFile string, flagName string, outputFil } var cleaner staleFlagCleaner - cleaner.init(configFile, flagName, isTreated) + err = cleaner.init(configFile, flagName, isTreated) + if err != nil { + log.Fatal(err) + } + newRoot := cleaner.run(parsed) if outputFileName == "" { diff --git a/go/src/staleFlagCleaner.go b/go/src/staleFlagCleaner.go index b2eec6731..267d24605 100644 --- a/go/src/staleFlagCleaner.go +++ b/go/src/staleFlagCleaner.go @@ -15,15 +15,15 @@ package src import ( "encoding/json" + "fmt" "go/token" "io/ioutil" - "log" "os" /* We have used dst package instead of official go ast package because ast package - does not keep positions of comments, we use dst package which keeps the positions - of comment in place. It is similiar to the ast package and have same functions as ast. + does not keep positions of comments, we use dst package which keeps the positions + of comment in place. It is similiar to the ast package and have same functions as ast. So you can use documentation of ast to see the details of helper functions. */ "github.com/dave/dst" @@ -68,10 +68,19 @@ var ( control = "control" ) var ( - strTrue = "true" + strTrue = "true" strFalse = "false" ) +// Defining a error class in here +type initError struct { + errStr string +} + +func (je *initError) Error() string { + return fmt.Sprintf("staleFlagCleaner initialization error: %s", je.errStr) +} + // Implementing this as whole class type staleFlagCleaner struct { configFile string @@ -88,51 +97,45 @@ type staleFlagCleaner struct { isTreated bool } -func (sfc *staleFlagCleaner) init(configFile string, flagName string, isTreated bool) { +func (sfc *staleFlagCleaner) init(configFile string, flagName string, isTreated bool) error { sfc.configFile = configFile sfc.flagName = flagName sfc.isTreated = isTreated sfc.valueMap = make(map[string]Value) sfc.functype = make(map[string]FlagAPI) - sfc.ParseJSON() + err := sfc.ParseJSON() + return err } // Parse json -func (sfc *staleFlagCleaner) ParseJSON() { +func (sfc *staleFlagCleaner) ParseJSON() error { jsonFile, err := os.Open(sfc.configFile) - if err != nil { - log.Fatalf("failed opening file: %v", err) - os.Exit(-1) + return &initError{"Failed opening the config file."} } - byteValue, _ := ioutil.ReadAll(jsonFile) + byteValue, err := ioutil.ReadAll(jsonFile) + if err != nil { + return &initError{"Failed processing the config file, unable to read it."} + } // we unmarshal our byteArray which contains our // jsonFile's content into 'methodProperties' which we defined above - json.Unmarshal(byteValue, &sfc.methods) + err = json.Unmarshal(byteValue, &sfc.methods) + if err != nil { + return &initError{"Failed processing the config file, unable to unmarshal json file."} + } // store it in a hashmap for _, element := range sfc.methods.Methods { sfc.functype[element.MethodName] = element } + return nil } // Gets the type of the flagAPI func (sfc *staleFlagCleaner) flagTypeAPI(callExpr *dst.CallExpr) API { var apiName string - var flagIndex int // -1 if flag or group not here - flagIndex = -1 - - for ind, expr := range callExpr.Args { - switch arg := expr.(type) { - case *dst.Ident: - if arg.Name == sfc.flagName { - flagIndex = ind - break - } - } - } switch d := callExpr.Fun.(type) { case *dst.Ident: @@ -144,14 +147,19 @@ func (sfc *staleFlagCleaner) flagTypeAPI(callExpr *dst.CallExpr) API { } if element, ok := sfc.functype[apiName]; ok { - if element.FlagIndex == flagIndex { - switch element.OfType { - case treated: - return _isTreated - case control: - return _isControl - default: - return _isUnknown + if element.FlagIndex < len(callExpr.Args) { + switch arg := callExpr.Args[element.FlagIndex].(type) { + case *dst.Ident: + if arg.Name == sfc.flagName { + switch element.OfType { + case treated: + return _isTreated + case control: + return _isControl + default: + return _isUnknown + } + } } } } @@ -292,8 +300,8 @@ func (sfc *staleFlagCleaner) checkForBoolLiterals(value dst.Expr) bool { /* Below function have this aim: -If Value is isUndefined or it is a bool literal, then we are not adding that to valueMap -if not then will add to valueMap. +If Value is isUndefined or it is a bool literal, then we are not adding that to valueMap, +otherwise we will add it to valueMap. This signifies whether variable has effect of flag or not. */ func (sfc *staleFlagCleaner) updateValueMapPost(name dst.Expr, value dst.Expr) { @@ -409,7 +417,6 @@ This wiil be used to delete the nodes and storing the values of expressions. func (sfc *staleFlagCleaner) post(n *dstutil.Cursor) bool { switch d := n.Node().(type) { case *dst.ValueSpec: - //need for loop here to delete the specific varible in delVal := sfc.DelValStmt(&d.Names, &d.Values) if delVal { n.Delete() diff --git a/go/test/input/init.go b/go/test/input/init.go index 008135193..53d594114 100644 --- a/go/test/input/init.go +++ b/go/test/input/init.go @@ -45,8 +45,7 @@ func (flgMthd FlagMethods) commonBehaviour(str string, flag2 PropFlag) bool { // GoExamples : This will act as a class type GoExamples struct { - flagMthds FlagMethods - + flagMthds FlagMethods localService, globalService, newFeatures, basicFeature bool } diff --git a/go/test/output/control/init.go b/go/test/output/control/init.go index d8b4eaeb0..0a3cafef2 100644 --- a/go/test/output/control/init.go +++ b/go/test/output/control/init.go @@ -43,8 +43,7 @@ func (flgMthd FlagMethods) commonBehaviour(str string, flag2 PropFlag) bool { // GoExamples : This will act as a class type GoExamples struct { - flagMthds FlagMethods - + flagMthds FlagMethods localService, globalService, newFeatures, basicFeature bool } diff --git a/go/test/output/treated/init.go b/go/test/output/treated/init.go index d8b4eaeb0..0a3cafef2 100644 --- a/go/test/output/treated/init.go +++ b/go/test/output/treated/init.go @@ -43,8 +43,7 @@ func (flgMthd FlagMethods) commonBehaviour(str string, flag2 PropFlag) bool { // GoExamples : This will act as a class type GoExamples struct { - flagMthds FlagMethods - + flagMthds FlagMethods localService, globalService, newFeatures, basicFeature bool } diff --git a/go/test/piranha_test.go b/go/test/piranha_test.go index e7993cef0..0df8d8884 100644 --- a/go/test/piranha_test.go +++ b/go/test/piranha_test.go @@ -81,6 +81,8 @@ func compFiles(file1 string, file2 string) bool { break } } + corrFile.Close() + treatFile.Close() return FileNotMatched } From 448cabc6ca398d2ee89a7cbb5b7dc0cde014da96 Mon Sep 17 00:00:00 2001 From: crekIron Date: Sun, 15 May 2022 14:46:06 +0530 Subject: [PATCH 9/9] Fixed logical error in main.go. Resolves issues in testing on Windows. Testing works both linux and windows --- go/example/treatedExample.go | 5 +---- go/main.go | 6 +++--- go/src/piranha.go | 1 + go/src/staleFlagCleaner.go | 15 +++++++-------- go/test/piranha_test.go | 14 +++++--------- 5 files changed, 17 insertions(+), 24 deletions(-) diff --git a/go/example/treatedExample.go b/go/example/treatedExample.go index 87c49533a..6434aeb71 100644 --- a/go/example/treatedExample.go +++ b/go/example/treatedExample.go @@ -11,30 +11,27 @@ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF express or implied. See the License for the specific language governing permissions and limitations under the License. */ + package testfiles import "fmt" func testExpressions(ge GoExamples) { var x, y bool = false, false - if x { fmt.Println("then-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } else { fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) || x`") } - fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && x`") fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x || y)`") fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && (x && y)`") fmt.Println("else-branch of `ge.flagMthds.treatedBehaviour(staleFlag) && y == x`") fmt.Println("then-braanch of `ge.flagMthds.controlBehaviour(staleFlag) || y == x`") - if y && x { fmt.Println("then-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } else { fmt.Println("else-branch of `ge.flagMthds.controlBehaviour(staleFlag) && y && x`") } - fmt.Println("then-braanch of `ge.flagMthds.controlBehaviour(staleFlag) || y || x`") } diff --git a/go/main.go b/go/main.go index a09401bb0..4733d5187 100644 --- a/go/main.go +++ b/go/main.go @@ -31,14 +31,14 @@ func main() { flag.StringVar(&flagName, "f", "STALE_FLAG", "Name of the stale flag.") // check treatedMode flag.StringVar(&modeName, "mode", "MODE_NAME", "If MODE_NAME=treated, then flag is treated, otherwise MODE_NAME=control, it is control.") - if modeName == "treated" { - isTreated = true - } // get outputFileName flag.StringVar(&outputFileName, "o", "OUTPUT", "Destination of the refactored output from piranha. If -o is not provided, then the source file is updated in place.") flag.Parse() + if modeName == "treated" { + isTreated = true + } src.RunPiranha(sourceFile, configFile, flagName, outputFileName, isTreated) } diff --git a/go/src/piranha.go b/go/src/piranha.go index 0c76f28a3..1bda3b104 100644 --- a/go/src/piranha.go +++ b/go/src/piranha.go @@ -102,4 +102,5 @@ func RunPiranha(sourceFile string, configFile string, flagName string, outputFil always starts with the dst.File type. */ decorator.Fprint(outputFile, newRoot.(*dst.File)) + outputFile.Close() } diff --git a/go/src/staleFlagCleaner.go b/go/src/staleFlagCleaner.go index 267d24605..6dfcce04f 100644 --- a/go/src/staleFlagCleaner.go +++ b/go/src/staleFlagCleaner.go @@ -64,8 +64,8 @@ const ( // Some useful global variables var ( - treated = "treated" - control = "control" + modeTreated = "treated" + modeControl = "control" ) var ( strTrue = "true" @@ -152,9 +152,9 @@ func (sfc *staleFlagCleaner) flagTypeAPI(callExpr *dst.CallExpr) API { case *dst.Ident: if arg.Name == sfc.flagName { switch element.OfType { - case treated: + case modeTreated: return _isTreated - case control: + case modeControl: return _isControl default: return _isUnknown @@ -304,9 +304,8 @@ If Value is isUndefined or it is a bool literal, then we are not adding that to otherwise we will add it to valueMap. This signifies whether variable has effect of flag or not. */ -func (sfc *staleFlagCleaner) updateValueMapPost(name dst.Expr, value dst.Expr) { +func (sfc *staleFlagCleaner) updateValueMapPost(name dst.Expr, value dst.Expr, doNotDelLiterals bool) { valOfExpr := sfc.evaluateExprNode(value) - doNotDelLiterals := sfc.checkForBoolLiterals(value) switch d := name.(type) { case *dst.Ident: if valOfExpr == isUndefined || doNotDelLiterals { @@ -348,7 +347,7 @@ func (sfc *staleFlagCleaner) DelValStmt(names *[]*dst.Ident, values *[]dst.Expr) if len((*values)) != 0 { valOfExpr = sfc.evaluateExprNode((*values)[ind]) doNotDelLiterals = sfc.checkForBoolLiterals((*values)[ind]) - sfc.updateValueMapPost((*names)[ind], (*values)[ind]) + sfc.updateValueMapPost((*names)[ind], (*values)[ind], doNotDelLiterals) } if (valOfExpr != isUndefined && !doNotDelLiterals) || (*names)[ind].Name == sfc.flagName || delCallExpr { @@ -386,7 +385,7 @@ func (sfc *staleFlagCleaner) DelAssStmt(names *[]dst.Expr, values *[]dst.Expr) b doNotDelLiterals = sfc.checkForBoolLiterals((*values)[ind]) // Need to see what to do with this thing - sfc.updateValueMapPost((*names)[ind], (*values)[ind]) + sfc.updateValueMapPost((*names)[ind], (*values)[ind], doNotDelLiterals) if (valOfExpr != isUndefined && !doNotDelLiterals) || delCallExpr { var trueIdent dst.Ident diff --git a/go/test/piranha_test.go b/go/test/piranha_test.go index 0df8d8884..49672234c 100644 --- a/go/test/piranha_test.go +++ b/go/test/piranha_test.go @@ -127,13 +127,9 @@ func TestFiles(t *testing.T) { fmt.Println("File Matched Sucessfully") } fmt.Println() - del := os.Remove("temp.go") - if del != nil { - log.Fatal(del) - } } fmt.Print("Testing with -mode control\n") - isTreated=false + isTreated = false for _, table := range tables { fmt.Print("Matching with: ") fmt.Println(table.outputControl) @@ -146,9 +142,9 @@ func TestFiles(t *testing.T) { fmt.Println("File Matched Sucessfully") } fmt.Println() - del := os.Remove("temp.go") - if del != nil { - log.Fatal(del) - } + } + del := os.Remove("temp.go") + if del != nil { + log.Fatal(del) } }