Don't put QString in static attributes

It crashed in some places on our code-base due to the so-called "static
initialization order fiasco".
As a solution, it turns the variable into a function. This shouldn't have
a penalty due to QStringLiteral.

Change-Id: I9f8a955afdff878dc2f0db16fec861d81250c243
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
Aleix Pol
2015-10-09 13:33:27 +02:00
committed by Aleix Pol Gonzalez
parent 954cabdde8
commit b899684a89
8 changed files with 86 additions and 86 deletions

View File

@@ -734,7 +734,7 @@ void Preprocessor::State::updateIncludeGuardState_helper(IncludeGuardStateHint h
#endif // DEBUG_INCLUDE_GUARD_TRACKING #endif // DEBUG_INCLUDE_GUARD_TRACKING
} }
const QString Preprocessor::configurationFileName = QLatin1String("<configuration>"); QString Preprocessor::configurationFileName() { return QStringLiteral("<configuration>"); }
Preprocessor::Preprocessor(Client *client, Environment *env) Preprocessor::Preprocessor(Client *client, Environment *env)
: m_client(client) : m_client(client)
@@ -1978,7 +1978,7 @@ void Preprocessor::handleIfDefDirective(bool checkUndefined, PPToken *tk)
// the macro is a feature constraint(e.g. QT_NO_XXX) // the macro is a feature constraint(e.g. QT_NO_XXX)
if (checkUndefined && macroName.startsWith("QT_NO_")) { if (checkUndefined && macroName.startsWith("QT_NO_")) {
if (macro->fileName() == configurationFileName) { if (macro->fileName() == configurationFileName()) {
// and it' defined in a pro file (e.g. DEFINES += QT_NO_QOBJECT) // and it' defined in a pro file (e.g. DEFINES += QT_NO_QOBJECT)
value = false; // take the branch value = false; // take the branch

View File

@@ -77,7 +77,7 @@ class CPLUSPLUS_EXPORT Preprocessor
typedef Internal::Value Value; typedef Internal::Value Value;
public: public:
static const QString configurationFileName; static QString configurationFileName();
public: public:
Preprocessor(Client *client, Environment *env); Preprocessor(Client *client, Environment *env);

View File

@@ -481,7 +481,7 @@ bool operator <(const ImportKey &i1, const ImportKey &i2)
return i1.compare(i2) < 0; return i1.compare(i2) < 0;
} }
const QString Export::LibraryTypeName = QLatin1String("%Library%"); QString Export::libraryTypeName() { return QStringLiteral("%Library%"); }
Export::Export() Export::Export()
: intrinsic(false) : intrinsic(false)

View File

@@ -131,10 +131,10 @@ bool operator <(const ImportKey &i1, const ImportKey &i2);
class QMLJS_EXPORT Export class QMLJS_EXPORT Export
{ {
public: public:
static const QString LibraryTypeName; static QString libraryTypeName();
Export(); Export();
Export(ImportKey exportName, QString pathRequired, bool intrinsic = false, Export(ImportKey exportName, QString pathRequired, bool intrinsic = false,
const QString &typeName = LibraryTypeName); const QString &typeName = libraryTypeName());
ImportKey exportName; ImportKey exportName;
QString pathRequired; QString pathRequired;
QString typeName; QString typeName;
@@ -211,9 +211,9 @@ public:
void removeCoreImport(const QString &importId); void removeCoreImport(const QString &importId);
void addExport(const QString &importId, const ImportKey &importKey, void addExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath, const QString &typeName = Export::LibraryTypeName); const QString &requiredPath, const QString &typeName = Export::libraryTypeName());
void removeExport(const QString &importId, const ImportKey &importKey, void removeExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath, const QString &typeName = Export::LibraryTypeName); const QString &requiredPath, const QString &typeName = Export::libraryTypeName());
void iterateOnCoreImports(const ViewerContext &vContext, void iterateOnCoreImports(const ViewerContext &vContext,
std::function<bool(const CoreImport &)> const &iterF) const; std::function<bool(const CoreImport &)> const &iterF) const;

View File

@@ -137,28 +137,28 @@ JsonValue *JsonValue::build(const QVariant &variant, JsonMemoryPool *pool)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
const QString JsonSchema::kType(QLatin1String("type")); QString JsonSchema::kType() { return QStringLiteral("type"); }
const QString JsonSchema::kProperties(QLatin1String("properties")); QString JsonSchema::kProperties() { return QStringLiteral("properties"); }
const QString JsonSchema::kPatternProperties(QLatin1String("patternProperties")); QString JsonSchema::kPatternProperties() { return QStringLiteral("patternProperties"); }
const QString JsonSchema::kAdditionalProperties(QLatin1String("additionalProperties")); QString JsonSchema::kAdditionalProperties() { return QStringLiteral("additionalProperties"); }
const QString JsonSchema::kItems(QLatin1String("items")); QString JsonSchema::kItems() { return QStringLiteral("items"); }
const QString JsonSchema::kAdditionalItems(QLatin1String("additionalItems")); QString JsonSchema::kAdditionalItems() { return QStringLiteral("additionalItems"); }
const QString JsonSchema::kRequired(QLatin1String("required")); QString JsonSchema::kRequired() { return QStringLiteral("required"); }
const QString JsonSchema::kDependencies(QLatin1String("dependencies")); QString JsonSchema::kDependencies() { return QStringLiteral("dependencies"); }
const QString JsonSchema::kMinimum(QLatin1String("minimum")); QString JsonSchema::kMinimum() { return QStringLiteral("minimum"); }
const QString JsonSchema::kMaximum(QLatin1String("maximum")); QString JsonSchema::kMaximum() { return QStringLiteral("maximum"); }
const QString JsonSchema::kExclusiveMinimum(QLatin1String("exclusiveMinimum")); QString JsonSchema::kExclusiveMinimum() { return QStringLiteral("exclusiveMinimum"); }
const QString JsonSchema::kExclusiveMaximum(QLatin1String("exclusiveMaximum")); QString JsonSchema::kExclusiveMaximum() { return QStringLiteral("exclusiveMaximum"); }
const QString JsonSchema::kMinItems(QLatin1String("minItems")); QString JsonSchema::kMinItems() { return QStringLiteral("minItems"); }
const QString JsonSchema::kMaxItems(QLatin1String("maxItems")); QString JsonSchema::kMaxItems() { return QStringLiteral("maxItems"); }
const QString JsonSchema::kUniqueItems(QLatin1String("uniqueItems")); QString JsonSchema::kUniqueItems() { return QStringLiteral("uniqueItems"); }
const QString JsonSchema::kPattern(QLatin1String("pattern")); QString JsonSchema::kPattern() { return QStringLiteral("pattern"); }
const QString JsonSchema::kMinLength(QLatin1String("minLength")); QString JsonSchema::kMinLength() { return QStringLiteral("minLength"); }
const QString JsonSchema::kMaxLength(QLatin1String("maxLength")); QString JsonSchema::kMaxLength() { return QStringLiteral("maxLength"); }
const QString JsonSchema::kTitle(QLatin1String("title")); QString JsonSchema::kTitle() { return QStringLiteral("title"); }
const QString JsonSchema::kDescription(QLatin1String("description")); QString JsonSchema::kDescription() { return QStringLiteral("description"); }
const QString JsonSchema::kExtends(QLatin1String("extends")); QString JsonSchema::kExtends() { return QStringLiteral("extends"); }
const QString JsonSchema::kRef(QLatin1String("$ref")); QString JsonSchema::kRef() { return QStringLiteral("$ref"); }
JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *manager) JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *manager)
: m_manager(manager) : m_manager(manager)
@@ -169,11 +169,11 @@ JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *man
bool JsonSchema::isTypeConstrained() const bool JsonSchema::isTypeConstrained() const
{ {
// Simple types // Simple types
if (JsonStringValue *sv = getStringValue(kType, currentValue())) if (JsonStringValue *sv = getStringValue(kType(), currentValue()))
return isCheckableType(sv->value()); return isCheckableType(sv->value());
// Union types // Union types
if (JsonArrayValue *av = getArrayValue(kType, currentValue())) { if (JsonArrayValue *av = getArrayValue(kType(), currentValue())) {
QTC_ASSERT(currentIndex() != -1, return false); QTC_ASSERT(currentIndex() != -1, return false);
QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false); QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false);
JsonStringValue *sv = av->elements().at(currentIndex())->toString(); JsonStringValue *sv = av->elements().at(currentIndex())->toString();
@@ -186,11 +186,11 @@ bool JsonSchema::isTypeConstrained() const
bool JsonSchema::acceptsType(const QString &type) const bool JsonSchema::acceptsType(const QString &type) const
{ {
// Simple types // Simple types
if (JsonStringValue *sv = getStringValue(kType, currentValue())) if (JsonStringValue *sv = getStringValue(kType(), currentValue()))
return typeMatches(sv->value(), type); return typeMatches(sv->value(), type);
// Union types // Union types
if (JsonArrayValue *av = getArrayValue(kType, currentValue())) { if (JsonArrayValue *av = getArrayValue(kType(), currentValue())) {
QTC_ASSERT(currentIndex() != -1, return false); QTC_ASSERT(currentIndex() != -1, return false);
QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false); QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false);
JsonStringValue *sv = av->elements().at(currentIndex())->toString(); JsonStringValue *sv = av->elements().at(currentIndex())->toString();
@@ -204,13 +204,13 @@ QStringList JsonSchema::validTypes(JsonObjectValue *v)
{ {
QStringList all; QStringList all;
if (JsonStringValue *sv = getStringValue(kType, v)) if (JsonStringValue *sv = getStringValue(kType(), v))
all.append(sv->value()); all.append(sv->value());
if (JsonObjectValue *ov = getObjectValue(kType, v)) if (JsonObjectValue *ov = getObjectValue(kType(), v))
return validTypes(ov); return validTypes(ov);
if (JsonArrayValue *av = getArrayValue(kType, v)) { if (JsonArrayValue *av = getArrayValue(kType(), v)) {
foreach (JsonValue *v, av->elements()) { foreach (JsonValue *v, av->elements()) {
if (JsonStringValue *sv = v->toString()) if (JsonStringValue *sv = v->toString())
all.append(sv->value()); all.append(sv->value());
@@ -252,14 +252,14 @@ QStringList JsonSchema::validTypes() const
bool JsonSchema::hasTypeSchema() const bool JsonSchema::hasTypeSchema() const
{ {
return getObjectValue(kType, currentValue()); return getObjectValue(kType(), currentValue());
} }
void JsonSchema::enterNestedTypeSchema() void JsonSchema::enterNestedTypeSchema()
{ {
QTC_ASSERT(hasTypeSchema(), return); QTC_ASSERT(hasTypeSchema(), return);
enter(getObjectValue(kType, currentValue())); enter(getObjectValue(kType(), currentValue()));
} }
QStringList JsonSchema::properties(JsonObjectValue *v) const QStringList JsonSchema::properties(JsonObjectValue *v) const
@@ -268,7 +268,7 @@ QStringList JsonSchema::properties(JsonObjectValue *v) const
QStringList all; QStringList all;
if (JsonObjectValue *ov = getObjectValue(kProperties, v)) { if (JsonObjectValue *ov = getObjectValue(kProperties(), v)) {
const MemberConstIterator cend = ov->members().constEnd(); const MemberConstIterator cend = ov->members().constEnd();
for (MemberConstIterator it = ov->members().constBegin(); it != cend; ++it) for (MemberConstIterator it = ov->members().constBegin(); it != cend; ++it)
if (hasPropertySchema(it.key())) if (hasPropertySchema(it.key()))
@@ -291,7 +291,7 @@ QStringList JsonSchema::properties() const
JsonObjectValue *JsonSchema::propertySchema(const QString &property, JsonObjectValue *JsonSchema::propertySchema(const QString &property,
JsonObjectValue *v) const JsonObjectValue *v) const
{ {
if (JsonObjectValue *ov = getObjectValue(kProperties, v)) { if (JsonObjectValue *ov = getObjectValue(kProperties(), v)) {
JsonValue *member = ov->member(property); JsonValue *member = ov->member(property);
if (member && member->kind() == JsonValue::Object) if (member && member->kind() == JsonValue::Object)
return member->toObject(); return member->toObject();
@@ -329,14 +329,14 @@ bool JsonSchema::hasItemSchema() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return getObjectValue(kItems, currentValue()); return getObjectValue(kItems(), currentValue());
} }
void JsonSchema::enterNestedItemSchema() void JsonSchema::enterNestedItemSchema()
{ {
QTC_ASSERT(hasItemSchema(), return); QTC_ASSERT(hasItemSchema(), return);
enter(getObjectValue(kItems, currentValue())); enter(getObjectValue(kItems(), currentValue()));
} }
/*! /*!
@@ -350,14 +350,14 @@ bool JsonSchema::hasItemArraySchema() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return getArrayValue(kItems, currentValue()); return getArrayValue(kItems(), currentValue());
} }
int JsonSchema::itemArraySchemaSize() const int JsonSchema::itemArraySchemaSize() const
{ {
QTC_ASSERT(hasItemArraySchema(), return false); QTC_ASSERT(hasItemArraySchema(), return false);
return getArrayValue(kItems, currentValue())->size(); return getArrayValue(kItems(), currentValue())->size();
} }
/*! /*!
@@ -377,7 +377,7 @@ bool JsonSchema::maybeEnterNestedArraySchema(int index)
QTC_ASSERT(itemArraySchemaSize(), return false); QTC_ASSERT(itemArraySchemaSize(), return false);
QTC_ASSERT(index >= 0 && index < itemArraySchemaSize(), return false); QTC_ASSERT(index >= 0 && index < itemArraySchemaSize(), return false);
JsonValue *v = getArrayValue(kItems, currentValue())->elements().at(index); JsonValue *v = getArrayValue(kItems(), currentValue())->elements().at(index);
return maybeEnter(v, Array, index); return maybeEnter(v, Array, index);
} }
@@ -391,12 +391,12 @@ bool JsonSchema::maybeEnterNestedArraySchema(int index)
*/ */
bool JsonSchema::hasUnionSchema() const bool JsonSchema::hasUnionSchema() const
{ {
return getArrayValue(kType, currentValue()); return getArrayValue(kType(), currentValue());
} }
int JsonSchema::unionSchemaSize() const int JsonSchema::unionSchemaSize() const
{ {
return getArrayValue(kType, currentValue())->size(); return getArrayValue(kType(), currentValue())->size();
} }
/*! /*!
@@ -416,7 +416,7 @@ bool JsonSchema::maybeEnterNestedUnionSchema(int index)
QTC_ASSERT(unionSchemaSize(), return false); QTC_ASSERT(unionSchemaSize(), return false);
QTC_ASSERT(index >= 0 && index < unionSchemaSize(), return false); QTC_ASSERT(index >= 0 && index < unionSchemaSize(), return false);
JsonValue *v = getArrayValue(kType, currentValue())->elements().at(index); JsonValue *v = getArrayValue(kType(), currentValue())->elements().at(index);
return maybeEnter(v, Union, index); return maybeEnter(v, Union, index);
} }
@@ -430,7 +430,7 @@ void JsonSchema::leaveNestedSchema()
bool JsonSchema::required() const bool JsonSchema::required() const
{ {
if (JsonBooleanValue *bv = getBooleanValue(kRequired, currentValue())) if (JsonBooleanValue *bv = getBooleanValue(kRequired(), currentValue()))
return bv->value(); return bv->value();
return false; return false;
@@ -440,21 +440,21 @@ bool JsonSchema::hasMinimum() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
return getDoubleValue(kMinimum, currentValue()); return getDoubleValue(kMinimum(), currentValue());
} }
double JsonSchema::minimum() const double JsonSchema::minimum() const
{ {
QTC_ASSERT(hasMinimum(), return 0); QTC_ASSERT(hasMinimum(), return 0);
return getDoubleValue(kMinimum, currentValue())->value(); return getDoubleValue(kMinimum(), currentValue())->value();
} }
bool JsonSchema::hasExclusiveMinimum() bool JsonSchema::hasExclusiveMinimum()
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMinimum, currentValue())) if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMinimum(), currentValue()))
return bv->value(); return bv->value();
return false; return false;
@@ -464,21 +464,21 @@ bool JsonSchema::hasMaximum() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
return getDoubleValue(kMaximum, currentValue()); return getDoubleValue(kMaximum(), currentValue());
} }
double JsonSchema::maximum() const double JsonSchema::maximum() const
{ {
QTC_ASSERT(hasMaximum(), return 0); QTC_ASSERT(hasMaximum(), return 0);
return getDoubleValue(kMaximum, currentValue())->value(); return getDoubleValue(kMaximum(), currentValue())->value();
} }
bool JsonSchema::hasExclusiveMaximum() bool JsonSchema::hasExclusiveMaximum()
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMaximum, currentValue())) if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMaximum(), currentValue()))
return bv->value(); return bv->value();
return false; return false;
@@ -488,7 +488,7 @@ QString JsonSchema::pattern() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return QString()); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return QString());
if (JsonStringValue *sv = getStringValue(kPattern, currentValue())) if (JsonStringValue *sv = getStringValue(kPattern(), currentValue()))
return sv->value(); return sv->value();
return QString(); return QString();
@@ -498,7 +498,7 @@ int JsonSchema::minimumLength() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1);
if (JsonDoubleValue *dv = getDoubleValue(kMinLength, currentValue())) if (JsonDoubleValue *dv = getDoubleValue(kMinLength(), currentValue()))
return dv->value(); return dv->value();
return -1; return -1;
@@ -508,7 +508,7 @@ int JsonSchema::maximumLength() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1);
if (JsonDoubleValue *dv = getDoubleValue(kMaxLength, currentValue())) if (JsonDoubleValue *dv = getDoubleValue(kMaxLength(), currentValue()))
return dv->value(); return dv->value();
return -1; return -1;
@@ -518,7 +518,7 @@ bool JsonSchema::hasAdditionalItems() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return currentValue()->member(kAdditionalItems); return currentValue()->member(kAdditionalItems());
} }
bool JsonSchema::maybeSchemaName(const QString &s) bool JsonSchema::maybeSchemaName(const QString &s)
@@ -600,7 +600,7 @@ void JsonSchema::leave()
JsonObjectValue *JsonSchema::resolveReference(JsonObjectValue *ov) const JsonObjectValue *JsonSchema::resolveReference(JsonObjectValue *ov) const
{ {
if (JsonStringValue *sv = getStringValue(kRef, ov)) { if (JsonStringValue *sv = getStringValue(kRef(), ov)) {
JsonSchema *referenced = m_manager->schemaByName(sv->value()); JsonSchema *referenced = m_manager->schemaByName(sv->value());
if (referenced) if (referenced)
return referenced->rootValue(); return referenced->rootValue();
@@ -611,7 +611,7 @@ JsonObjectValue *JsonSchema::resolveReference(JsonObjectValue *ov) const
JsonObjectValue *JsonSchema::resolveBase(JsonObjectValue *ov) const JsonObjectValue *JsonSchema::resolveBase(JsonObjectValue *ov) const
{ {
if (JsonValue *v = ov->member(kExtends)) { if (JsonValue *v = ov->member(kExtends())) {
if (v->kind() == JsonValue::String) { if (v->kind() == JsonValue::String) {
JsonSchema *schema = m_manager->schemaByName(v->toString()->value()); JsonSchema *schema = m_manager->schemaByName(v->toString()->value());
if (schema) if (schema)

View File

@@ -355,28 +355,28 @@ private:
static bool maybeSchemaName(const QString &s); static bool maybeSchemaName(const QString &s);
static const QString kType; static QString kType();
static const QString kProperties; static QString kProperties();
static const QString kPatternProperties; static QString kPatternProperties();
static const QString kAdditionalProperties; static QString kAdditionalProperties();
static const QString kItems; static QString kItems();
static const QString kAdditionalItems; static QString kAdditionalItems();
static const QString kRequired; static QString kRequired();
static const QString kDependencies; static QString kDependencies();
static const QString kMinimum; static QString kMinimum();
static const QString kMaximum; static QString kMaximum();
static const QString kExclusiveMinimum; static QString kExclusiveMinimum();
static const QString kExclusiveMaximum; static QString kExclusiveMaximum();
static const QString kMinItems; static QString kMinItems();
static const QString kMaxItems; static QString kMaxItems();
static const QString kUniqueItems; static QString kUniqueItems();
static const QString kPattern; static QString kPattern();
static const QString kMinLength; static QString kMinLength();
static const QString kMaxLength; static QString kMaxLength();
static const QString kTitle; static QString kTitle();
static const QString kDescription; static QString kDescription();
static const QString kExtends; static QString kExtends();
static const QString kRef; static QString kRef();
struct Context struct Context
{ {

View File

@@ -253,7 +253,7 @@ QString CppModelManager::editorConfigurationFileName()
QString CppModelManager::configurationFileName() QString CppModelManager::configurationFileName()
{ {
return Preprocessor::configurationFileName; return Preprocessor::configurationFileName();
} }
void CppModelManager::updateModifiedSourceFiles() void CppModelManager::updateModifiedSourceFiles()

View File

@@ -154,7 +154,7 @@ static QString qualifiedTypeNameForContext(const ObjectValue *objectValue,
case ImportType::Library: case ImportType::Library:
{ {
QString typeName = objectValue->className(); QString typeName = objectValue->className();
if (!e.typeName.isEmpty() && e.typeName != Export::LibraryTypeName) { if (!e.typeName.isEmpty() && e.typeName != Export::libraryTypeName()) {
typeName = e.typeName; typeName = e.typeName;
if (typeName != objectValue->className()) if (typeName != objectValue->className())
qCWarning(qmljsLog) << "Outdated classname " << objectValue->className() qCWarning(qmljsLog) << "Outdated classname " << objectValue->className()