Skip to content

Commit

Permalink
Renaming generic types in is cast from non-optional to optional typ…
Browse files Browse the repository at this point in the history
…e or vice versa

Reviewers: krzysztof.siejkowski, michal.zielinski

Reviewed By: krzysztof.siejkowski, michal.zielinski

Subscribers: michal.zielinski, krzysztof.siejkowski

Differential Revision: https://phabricator.polidea.com/D2872
  • Loading branch information
jerzyKleszcz committed Mar 7, 2018
1 parent c8340d3 commit 73247f6
Show file tree
Hide file tree
Showing 5 changed files with 782 additions and 204 deletions.
129 changes: 94 additions & 35 deletions swift/lib/Obfuscation/ExpressionParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,37 @@ SymbolsOrError parseCallExpressionWithArguments(CallExpr* CallExpression) {

return Symbols;
}

SymbolsOrError
parseGenericParameters(BoundGenericType *BoundGenericType,
SourceLoc OpeningAngleBracketLoc) {
std::vector<SymbolWithRange> Symbols;
auto Parameters = BoundGenericType->getGenericArgs();
for (auto Parameter : Parameters) {
NominalTypeDecl *ParameterDecl = nullptr;
if (OptionalType::classof(Parameter.getPointer())) {
ParameterDecl =
Parameter->getOptionalObjectType()->getAnyNominal();
} else {
ParameterDecl = Parameter->getAnyNominal();
}
auto ParameterSymbol = parse(ParameterDecl);
if (auto Error = ParameterSymbol.takeError()) {
return std::move(Error);
}
auto ParameterName =
ParameterDecl->getBaseName().getIdentifier().str();
auto GenericArgRange =
rangeOfFirstOccurenceOfStringInSourceLoc(ParameterName,
OpeningAngleBracketLoc);
if (auto Error = GenericArgRange.takeError()) {
return std::move(Error);
}
Symbols.push_back(SymbolWithRange(ParameterSymbol.get(),
GenericArgRange.get()));
}
return Symbols;
}

SymbolsOrError parse(CallExpr* CallExpression) {
if (CallExpression->hasArgumentLabelLocs()) {
Expand All @@ -142,57 +173,85 @@ SymbolsOrError parse(CallExpr* CallExpression) {
// representing the CastType (cast-to type) so we have to extract it
// from the EnumIsCaseExpression.
SymbolsOrError parse(EnumIsCaseExpr* EnumIsCaseExpression) {
NominalTypeDecl *CastTypeDeclaration = nullptr;
SourceLoc IsKeywordSourceLoc;
ExplicitCastExpr *ExplicitCastExpression = nullptr;

// This callback invoked using forEachChildExpr() is used to extract the
// declaration of the CastType and the location of the `is` keyword.
const std::function<Expr*(Expr*)> &callback =
[&CastTypeDeclaration, &IsKeywordSourceLoc](Expr* Child) -> Expr* {
[&ExplicitCastExpression](Expr* Child) -> Expr* {

// We're looking for CoerceExpr (non-optional to optional type cast)
// or ConditionalCheckedCastExpr (optional to non-optional type cast)
// which both are subclasses of ExplicitCastExpr.
if (auto *ExplicitCastExpression = dyn_cast<ExplicitCastExpr>(Child)) {

Type CastType = ExplicitCastExpression->getCastTypeLoc().getType();

// The data representing the location of the CastType in the expression
// seems to be impossible to retrieve from the EnumIsCastExpression
// and its subexpressions. We have to calculate the CastType location
// later using `is` keyword and CastType name.
IsKeywordSourceLoc = ExplicitCastExpression->getAsLoc();

if (ConditionalCheckedCastExpr::classof(ExplicitCastExpression)) {
CastTypeDeclaration = CastType->getAnyNominal();
} else if (CoerceExpr::classof(ExplicitCastExpression)) {
CastTypeDeclaration = CastType->getOptionalObjectType()->getAnyNominal();
}

if (ExplicitCastExpr::classof(Child)) {
ExplicitCastExpression = dyn_cast<ExplicitCastExpr>(Child);
}

return Child;
};
EnumIsCaseExpression->forEachChildExpr(callback);

if (CastTypeDeclaration != nullptr) {
auto SingleSymbolOrError = parse(CastTypeDeclaration);
if (auto Error = SingleSymbolOrError.takeError()) {
return std::move(Error);
}
auto CastTypeSymbol = SingleSymbolOrError.get();
if (ExplicitCastExpression != nullptr) {
auto CastType = ExplicitCastExpression->getCastTypeLoc().getType();

auto CastTypeName = typeName(CastTypeDeclaration);
auto RangeOrError =
rangeOfFirstOccurenceOfStringInSourceLoc(CastTypeName,
IsKeywordSourceLoc);
if (auto Error = RangeOrError.takeError()) {
return std::move(Error);
// The data representing the location of the CastType in the expression
// seems to be impossible to retrieve from the EnumIsCastExpression
// and its subexpressions. We have to calculate the CastType location
// later using `is` keyword and CastType name.
auto IsKeywordSourceLoc = ExplicitCastExpression->getAsLoc();

Type UnwrappedCastType;
if (ConditionalCheckedCastExpr::classof(ExplicitCastExpression)) {
UnwrappedCastType = CastType;
} else if (CoerceExpr::classof(ExplicitCastExpression)) {
UnwrappedCastType = CastType->getOptionalObjectType();
} else {
return stringError("Unsupported type of explicit cast expression");
}
auto CastTypeRange = RangeOrError.get();

std::vector<SymbolWithRange> Symbols;
Symbols.push_back(SymbolWithRange(CastTypeSymbol, CastTypeRange));
return Symbols;
NominalTypeDecl *CastTypeDeclaration = UnwrappedCastType->getAnyNominal();

if (CastTypeDeclaration != nullptr) {
auto CastTypeSymbol = parse(CastTypeDeclaration);
if (auto Error = CastTypeSymbol.takeError()) {
return std::move(Error);
}

auto CastTypeName =
CastTypeDeclaration->getBaseName().getIdentifier().str();
auto CastTypeRange =
rangeOfFirstOccurenceOfStringInSourceLoc(CastTypeName,
IsKeywordSourceLoc);
if (auto Error = CastTypeRange.takeError()) {
return std::move(Error);
}

std::vector<SymbolWithRange> Symbols;
Symbols.push_back(SymbolWithRange(CastTypeSymbol.get(),
CastTypeRange.get()));

if (auto *GenericBoundType =
dyn_cast<BoundGenericType>(UnwrappedCastType.getPointer())) {

auto GenericNameEndLoc = CastTypeRange.get().getEnd();
auto OpeningAngleBracketRange =
rangeOfFirstOccurenceOfStringInSourceLoc("<", GenericNameEndLoc);
if (auto Error = OpeningAngleBracketRange.takeError()) {
return std::move(Error);
}
auto OpeningAngleBracketLoc = OpeningAngleBracketRange.get().getStart();

auto GenericParamsSymbols =
parseGenericParameters(GenericBoundType, OpeningAngleBracketLoc);
if (auto Error = GenericParamsSymbols.takeError()) {
return std::move(Error);
}

copyToVector(GenericParamsSymbols.get(), Symbols);
}

return Symbols;
}
}

return stringError("Failed to extract the cast-to type symbol"
Expand Down
Loading

0 comments on commit 73247f6

Please sign in to comment.