trufflesuite / truffle-compile

Compiler helper and artifact manager
22 stars 46 forks source link

Need more consistent compilation selection when name collisions happen #68

Open wbt opened 6 years ago

wbt commented 6 years ago

When files in the /contracts/ directory of a truffle project collectively contain more than one contract with the same contract name, Truffle seems to choose which one to compile in a random or alternating fashion (I haven't yet dug deep enough to see exactly how that gets determined now). This means that running what seems to be the same thing twice in sequence can produce different results, if the contents of the contracts in the different files differ.

This can be very hard to debug, because the programmer may not be modifying the files that get used when running, as which file(s) those are change from run to run in a way that is not obvious or intuitive for the programmer.

The appearance of this issue can be attributed to user error, in that ideally such a name collision should not occur. However, some version control systems can produce this situation. For example, Subversion occasionally drops in older revisions when it detects a potential conflict, and the "poor man's version control" of keeping multiple copies of a file with differing filenames to track progressive versions (or to build an MCVE diff for a bug report) would also produce this issue, when those copies are kept in the same directory. I don't advocate for either of those two methods (generally, go with git) but they do get used.

As a heuristic that I think will generally match programmer intent, I suggest that when the set of files being compiled contains contract name collisions, the contract from the file with the latest modified date[time] should be used. If there is an exact tie for file modification date, I suggest using the one from the file with the fewest number of contracts (to encourage modularity), the one which occurs later in a file if both are in the same file (like CSS), the longer one (contracts tend to grow more often than shrink during at least early development), and finally the one with the lowest hash value, as tiebreakers. If there's still a tie by that point, the status quo solution should be OK.

This will make compilation more deterministic and predictable, to facilitate debugging.