blob: 8f4330c72b9ac0911aac6846987c3f2d359a16a7 [file] [log] [blame]
// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDebugEvent;
import com.android.tools.r8.graph.DexDebugEvent.SetFile;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.shaking.ProguardConfiguration;
import java.util.Arrays;
/**
* Visit program {@link DexClass}es and replace their sourceFile with the given string.
*
* If -keepattribute SourceFile is not set, we rather remove that attribute.
*/
public class SourceFileRewriter {
private final AppView<?> appView;
public SourceFileRewriter(AppView<?> appView) {
this.appView = appView;
}
public void run() {
ProguardConfiguration proguardConfiguration = appView.options().getProguardConfiguration();
String renameSourceFile = proguardConfiguration.getRenameSourceFileAttribute();
// Return early if a user wants to keep the current source file attribute as-is.
if (renameSourceFile == null && proguardConfiguration.getKeepAttributes().sourceFile) {
return;
}
// Now, the user wants either to remove source file attribute or to rename it.
DexString dexRenameSourceFile =
renameSourceFile == null
? appView.dexItemFactory().createString("")
: appView.dexItemFactory().createString(renameSourceFile);
for (DexClass clazz : appView.appInfo().classes()) {
clazz.sourceFile = dexRenameSourceFile;
clazz.forEachMethod(encodedMethod -> {
// Abstract methods do not have code_item.
if (encodedMethod.shouldNotHaveCode()) {
return;
}
Code code = encodedMethod.getCode();
if (code == null) {
return;
}
if (code.isDexCode()) {
DexDebugInfo dexDebugInfo = code.asDexCode().getDebugInfo();
if (dexDebugInfo == null) {
return;
}
// Thanks to a single global source file, we can safely remove DBG_SET_FILE entirely.
dexDebugInfo.events =
Arrays.stream(dexDebugInfo.events)
.filter(dexDebugEvent -> !(dexDebugEvent instanceof SetFile))
.toArray(DexDebugEvent[]::new);
} else {
assert code.isCfCode();
// CF has nothing equivalent to SetFile, so there is nothing to remove.
}
});
}
}
}