Omit needless words: prepend "is" to Boolean property names.

Prepend       "is" to        Boolean property names (e.g., "empty" becomes
"isEmpty") unless the property name strongly indicates its Boolean
nature or we're   likely to ruin the name. Therefore, the  presence of
one of the following in  the property name will suppress   this
transformation:

* An auxiliary verb, such as "is", "has", "may", "should", or "will".

* A word ending in "s", indicating either a plural (for which
  prepending "is" would be incorrect) or a verb in the continuous
  tense (which indicates its Boolean nature, e.g., "translates" in
  "translatesCoordinates").

Swift SVN r32458
This commit is contained in:
Doug Gregor
2015-10-06 07:03:17 +00:00
parent bf55d2712e
commit 7778790a68
8 changed files with 102 additions and 19 deletions

View File

@@ -47,6 +47,9 @@ PartOfSpeech swift::getPartOfSpeech(StringRef word) {
#define VERB(Word) \
if (word.equals_lower(#Word)) \
return PartOfSpeech::Verb;
#define AUXILIARY_VERB(Word) \
if (word.equals_lower(#Word)) \
return PartOfSpeech::AuxiliaryVerb;
#include "PartsOfSpeech.def"
// Identify gerunds, which always end in "ing".
@@ -603,6 +606,7 @@ static StringRef omitNeedlessWords(StringRef name,
break;
case PartOfSpeech::Unknown:
case PartOfSpeech::AuxiliaryVerb:
// Assume it's a noun or adjective; don't strip anything.
break;
}
@@ -644,11 +648,6 @@ static StringRef omitNeedlessWords(StringRef name,
return name;
}
/// Determine whether this is a "bad" first argument label.
static bool isBadFirstArgumentLabel(StringRef name) {
return name == "flag";
}
/// Whether this word can be used to split a first selector piece where the
/// first parameter is of Boolean type.
static bool canSplitForBooleanParameter(StringRef word) {
@@ -723,6 +722,25 @@ static bool omitNeedlessWordsMatchingFirstArgumentLabel(
return true;
}
/// Determine whether the given word indicates a boolean result.
static bool nameIndicatesBooleanResult(StringRef name) {
bool isFirstWord = true;
for (auto word: camel_case::getWords(name)) {
// Auxiliary verbs indicate Boolean results.
if (getPartOfSpeech(word) == PartOfSpeech::AuxiliaryVerb)
return true;
// Words that end in "s" indicate either Boolean results---it
// could be a verb in the present continuous tense---or some kind
// of plural, for which "is" would be inappropriate anyway.
if (word.back() == 's')
return true;
}
return false;
}
bool swift::omitNeedlessWords(StringRef &baseName,
MutableArrayRef<StringRef> argNames,
StringRef firstParamName,
@@ -730,6 +748,7 @@ bool swift::omitNeedlessWords(StringRef &baseName,
OmissionTypeName contextType,
ArrayRef<OmissionTypeName> paramTypes,
bool returnsSelf,
bool isProperty,
StringScratchSpace &scratch) {
bool anyChanges = false;
@@ -746,14 +765,26 @@ bool swift::omitNeedlessWords(StringRef &baseName,
}
// Treat zero-parameter methods and properties the same way.
if (paramTypes.empty() && resultTypeMatchesContext) {
StringRef newBaseName = ::omitNeedlessWords(
baseName,
returnsSelf ? contextType : resultType,
NameRole::Property,
scratch);
if (newBaseName != baseName) {
baseName = newBaseName;
if (paramTypes.empty()) {
if (resultTypeMatchesContext) {
StringRef newBaseName = ::omitNeedlessWords(
baseName,
returnsSelf ? contextType : resultType,
NameRole::Property,
scratch);
if (newBaseName != baseName) {
baseName = newBaseName;
anyChanges = true;
}
}
// Boolean properties should start with "is", unless their
// first word already implies a Boolean result.
if (resultType.isBoolean() && isProperty &&
!nameIndicatesBooleanResult(baseName)) {
SmallString<32> newName("is");
camel_case::appendSentenceCase(newName, baseName);
baseName = scratch.copyString(newName);
anyChanges = true;
}
@@ -825,6 +856,7 @@ bool swift::omitNeedlessWords(StringRef &baseName,
break;
case PartOfSpeech::Unknown:
case PartOfSpeech::AuxiliaryVerb:
++nameWordRevIter;
break;
}