Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ilya.Kazakevich
2014-10-07 23:40:41 +04:00
52 changed files with 721 additions and 368 deletions
@@ -152,7 +152,7 @@ public class PositionManagerImpl implements PositionManager {
return SourcePosition.createFromLine(psiFile, -1);
}
final MethodFinder finder = new MethodFinder(location.declaringType().name(), methodSignature);
final MethodFinder finder = new MethodFinder(location.declaringType().name(), methodName, methodSignature);
psiFile.accept(finder);
final PsiMethod compiledMethod = finder.getCompiledMethod();
@@ -382,11 +382,13 @@ public class PositionManagerImpl implements PositionManager {
private class MethodFinder extends JavaRecursiveElementVisitor {
private final String myClassName;
private PsiClass myCompiledClass;
private final String myMethodName;
private final String myMethodSignature;
private PsiMethod myCompiledMethod;
public MethodFinder(final String className, final String methodSignature) {
public MethodFinder(final String className, final String methodName, final String methodSignature) {
myClassName = className;
myMethodName = methodName;
myMethodSignature = methodSignature;
}
@@ -409,9 +411,8 @@ public class PositionManagerImpl implements PositionManager {
if(containingClass != null &&
containingClass.equals(myCompiledClass) &&
methodName.equals(methodName) &&
methodName.equals(myMethodName) &&
JVMNameUtil.getJVMSignature(method).getName(myDebugProcess).equals(myMethodSignature)) {
myCompiledMethod = method;
}
}
@@ -2054,7 +2054,7 @@ public class JavaDocInfoGenerator {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
myBuffer.append(expression.getMethodExpression().getText()).append("(");
expression.getArgumentList().acceptChildren(this);
expression.getArgumentList().accept(this);
myBuffer.append(")");
}
@@ -37,6 +37,24 @@ import javax.swing.*;
public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements PsiLambdaExpression {
private static final ControlFlowPolicy ourPolicy = new ControlFlowPolicy() {
@Nullable
@Override
public PsiVariable getUsedVariable(@NotNull PsiReferenceExpression refExpr) {
return null;
}
@Override
public boolean isParameterAccepted(@NotNull PsiParameter psiParameter) {
return true;
}
@Override
public boolean isLocalVariableAccepted(@NotNull PsiLocalVariable psiVariable) {
return true;
}
};
public PsiLambdaExpressionImpl() {
super(JavaElementType.LAMBDA_EXPRESSION);
}
@@ -92,9 +110,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
final PsiElement body = getBody();
if (body instanceof PsiCodeBlock) {
try {
ControlFlow controlFlow =
ControlFlowFactory.getInstance(getProject()).getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy
.getInstance());
ControlFlow controlFlow = ControlFlowFactory.getInstance(getProject()).getControlFlow(body, ourPolicy);
int startOffset = controlFlow.getStartOffset(body);
int endOffset = controlFlow.getEndOffset(body);
if (startOffset != -1 && endOffset != -1 && ControlFlowUtil.canCompleteNormally(controlFlow, startOffset, endOffset)) {
@@ -0,0 +1,21 @@
class Scratch
{
public static class PredicatedProposal<T>
{
private final Discriminator<? super T> pred = null;
public Discriminator<? super T> get()
{
return this.pred;
}
}
public static interface Discriminator<T extends String> extends Predicate<T>
{
}
interface Predicate<T> {
boolean val(T t);
}
}
@@ -0,0 +1,41 @@
import java.io.IOException;
class Test {
{
queryForObject(
(rs) -> {
try {
return readValue(rs);
} catch (IOException e) {
return new UserOptions();
}
}
);
}
UserOptions readValue(String content) throws IOException {
System.out.println(content);
return null;
}
UserOptions readValue(Integer i) throws IOException {
System.out.println(i);
return null;
}
void queryForObject(Mapper rowMapper) {
System.out.println(rowMapper);
}
void queryForObject(String requiredType) {
System.out.println(requiredType);
}
interface Mapper {
UserOptions mapRow(String rs) throws IOException;
}
class UserOptions {}
}
@@ -0,0 +1 @@
<html><head> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><small><b><a href="psi_element://Test"><code>Test</code></a></b></small><PRE>public <a href="psi_element://java.lang.String"><code>String</code></a> <b>field = foo(&quot;&quot;, &quot;&quot;)</b></PRE></body></html>
@@ -0,0 +1,7 @@
class Test {
public String field = foo("", "");
String foo(String s, String s1) {
return s;
}
}
@@ -211,6 +211,14 @@ foo->bar
'''
}
public void "test inside word"() {
myFixture.configureByText "a.c", 'foo fox f<caret>bar'
complete()
myFixture.checkResult 'foo fox fox<caret>bar'
complete()
myFixture.checkResult 'foo fox foo<caret>bar'
}
private void complete() {
myFixture.performEditorAction(IdeActions.ACTION_HIPPIE_COMPLETION)
}
@@ -380,6 +380,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
//jdk should propagate LL 1.4 but actually it provides LL 1.7?!
public void testCastObjectToIntJdk14() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_4, false); }
public void testIDEA127767() {
doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
}
public void testHiddenMethodsOfAnonymousClass() throws Exception {
doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
}
@@ -42,6 +42,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
public void testVoidValueCompatibilityOfImplicitlyTypedLambda() throws Exception {
doTest();
}
public void testVoidValueCompatibilityCachedControlFlow() throws Exception {
doTest();
}
public void testIDEA102800() throws Exception {
doTest();
@@ -96,6 +96,10 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
doTestField();
}
public void testCommaInsideArgsList() throws Exception {
doTestField();
}
public void testEnumConstantOrdinal() throws Exception {
PsiClass psiClass = getTestClass();
PsiField field = psiClass.getFields() [0];
@@ -55,8 +55,8 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler {
public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
int offset = editor.getCaretModel().getOffset();
if (editor.isViewer() || editor.getDocument().getRangeGuard(offset, offset) != null) {
int caretOffset = editor.getCaretModel().getOffset();
if (editor.isViewer() || editor.getDocument().getRangeGuard(caretOffset, caretOffset) != null) {
editor.getDocument().fireReadOnlyModificationAttempt();
CodeInsightUtilBase.showReadOnlyViewWarning(editor);
return;
@@ -87,8 +87,7 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler {
CompletionVariant nextVariant = computeNextVariant(editor, oldPrefix, lastProposedVariant, data, file, fromOtherFiles, false);
if (nextVariant == null) return;
int replacementEnd = data.startOffset + data.myWordUnderCursor.length();
editor.getDocument().replaceString(data.startOffset, replacementEnd, nextVariant.variant);
editor.getDocument().replaceString(data.startOffset, caretOffset, nextVariant.variant);
editor.getCaretModel().moveToOffset(data.startOffset + nextVariant.variant.length());
completionState.lastProposedVariant = nextVariant;
completionState.fromOtherFiles = nextVariant.editor != editor;
@@ -44,7 +44,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -65,25 +64,17 @@ public class NewScratchFileAction extends AnAction implements DumbAware {
public static List<String> getLastUsedLanguagesIds(Project project) {
String[] values = PropertiesComponent.getInstance(project).getValues(ScratchpadManager.class.getName());
if (values == null) {
return ContainerUtil.emptyList();
}
return ContainerUtil.list(values);
return values == null ? ContainerUtil.<String>emptyList() : ContainerUtil.list(values);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final Project project = e.getProject();
if (project == null) return;
Language context = null;
PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
if (file != null) {
context = file.getLanguage();
}
Language context = file != null ? file.getLanguage() : null;
ListPopup popup = buildLanguagePopup(project, context, new Consumer<Language>() {
@Override
public void consume(Language language) {
@@ -98,7 +89,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware {
@NotNull
static ListPopup buildLanguagePopup(@NotNull Project project, @Nullable Language context, final Consumer<Language> onChoosen) {
List<Language> languages = LanguageUtil.getFileLanguages();
final List<String> ids = new ArrayList<String>(getLastUsedLanguagesIds(project));
final List<String> ids = ContainerUtil.newArrayList(getLastUsedLanguagesIds(project));
if (context != null) {
ids.add(context.getID());
}
@@ -108,7 +99,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware {
ContainerUtil.sort(languages, new Comparator<Language>() {
@Override
public int compare(Language o1, Language o2) {
public int compare(@NotNull Language o1, @NotNull Language o2) {
int ind1 = ids.indexOf(o1.getID());
int ind2 = ids.indexOf(o2.getID());
if (ind1 == -1) ind1 = 666;
@@ -26,9 +26,10 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class ScratchpadManagerImpl extends ScratchpadManager implements Disposable {
private final Project myProject;
@@ -61,7 +62,7 @@ public class ScratchpadManagerImpl extends ScratchpadManager implements Disposab
private static void updateHistory(Project project, Language language) {
String[] values = PropertiesComponent.getInstance(project).getValues(ScratchpadManager.class.getName());
ArrayList<String> lastUsed = new ArrayList<String>(5);
List<String> lastUsed = ContainerUtil.newArrayListWithCapacity(5);
lastUsed.add(language.getID());
if (values != null) {
for (String value : values) {
@@ -132,7 +132,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
protected MasterDetailsComponent(MasterDetailsState state) {
myState = state;
mySplitter = isNewProjectSettings() ? new OnePixelSplitter(false, .2f) : new JBSplitter(false, .2f);
mySplitter = isNewProjectSettings() || isNewSettingsView() ? new OnePixelSplitter(false, .2f) : new JBSplitter(false, .2f);
mySplitter.setSplitterProportionKey("ProjectStructure.SecondLevelElements");
mySplitter.setHonorComponentsMinimumSize(true);
@@ -141,9 +141,6 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
private boolean isNewProjectSettings() {
if (ApplicationManager.getApplication().isInternal() && Registry.is("ide.new.settings.view")) {
return true;
}
if (!Registry.is("ide.new.project.settings")) {
return false;
}
@@ -157,6 +154,10 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
}
private boolean isNewSettingsView() {
return ApplicationManager.getApplication().isInternal() && Registry.is("ide.new.settings.view");
}
protected void reInitWholePanelIfNeeded() {
if (!myToReInitWholePanel) return;
@@ -188,7 +189,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
};
if (isNewProjectSettings()) {
if (isNewProjectSettings() || isNewSettingsView()) {
ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTree);
DefaultActionGroup group = createToolbarActionGroup();
if (group != null) {
@@ -206,6 +207,9 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
final JPanel right = new JPanel(new BorderLayout());
right.add(myDetails.getComponent(), BorderLayout.CENTER);
if (!isNewProjectSettings() && isNewSettingsView()) {
right.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
}
mySplitter.setSecondComponent(right);
@@ -299,7 +303,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
private void initToolbar() {
if (isNewProjectSettings()) return;
if (isNewProjectSettings() || isNewSettingsView()) return;
DefaultActionGroup group = createToolbarActionGroup();
if (group != null) {
final JComponent component = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
@@ -569,17 +569,23 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI {
}
private void paintMacThumb(Graphics g, Rectangle thumbBounds) {
if (myMacScrollbarHidden) return;
thumbBounds = getMacScrollBarBounds(thumbBounds, true);
Graphics2D g2d = (Graphics2D)g;
RenderingHints oldHints = g2d.getRenderingHints();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(adjustColor(new JBColor(Gray._0, Gray._128)));
JBColor baseColor = new JBColor(Gray._0, Gray._128);
int arc = Math.min(thumbBounds.width, thumbBounds.height);
g2d.fillRoundRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, arc, arc);
if (alwaysShowTrack()) {
g2d.setColor(new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), UIUtil.isUnderDarcula() ? 100 : 40));
g2d.drawRoundRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, arc, arc);
}
if (!myMacScrollbarHidden) {
g2d.setColor(adjustColor(baseColor));
g2d.fillRoundRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, arc, arc);
}
g2d.setRenderingHints(oldHints);
}
@@ -164,7 +164,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
ConfigurableGroup[] group = getConfigurableGroups(project, true);
group = filterEmptyGroups(group);
final Configurable configurable2Select = findConfigurable2Select(id2Select, group);
final Configurable configurable2Select = id2Select == null ? null : new ConfigurableVisitor.ByID(id2Select).find(group);
if (ApplicationManager.getApplication().isInternal() && Registry.is("ide.new.settings.view")) {
new SettingsDialog(getProject(project), group, configurable2Select, filter).show();
@@ -183,31 +183,6 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
dialog.show();
}
@Nullable
private static Configurable findConfigurable2Select(String id2Select, ConfigurableGroup[] group) {
for (ConfigurableGroup configurableGroup : group) {
for (Configurable configurable : configurableGroup.getConfigurables()) {
final Configurable conf = containsId(id2Select, configurable);
if (conf != null) return conf;
}
}
return null;
}
@Nullable
private static Configurable containsId(String id2Select, Configurable configurable) {
if (configurable instanceof SearchableConfigurable && id2Select.equals(((SearchableConfigurable)configurable).getId())) {
return configurable;
}
if (configurable instanceof SearchableConfigurable.Parent) {
for (Configurable subConfigurable : ((SearchableConfigurable.Parent)configurable).getConfigurables()) {
final Configurable config = containsId(id2Select, subConfigurable);
if (config != null) return config;
}
}
return null;
}
@Override
public void showSettingsDialog(@NotNull final Project project, final Configurable toSelect) {
getDialog(project, getConfigurableGroups(project, true), toSelect).show();
@@ -22,15 +22,21 @@ import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.ui.GuiUtils;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author stathik
@@ -41,9 +47,9 @@ public class PluginInstaller {
private PluginInstaller() { }
public static boolean prepareToInstall(List<PluginNode> pluginsToInstall, List<IdeaPluginDescriptor> allPlugins) {
HashSet<PluginNode> dependant = new HashSet<PluginNode>();
boolean install = prepareToInstall(pluginsToInstall, allPlugins, dependant);
public static boolean prepareToInstall(List<PluginNode> pluginsToInstall, List<IdeaPluginDescriptor> allPlugins, @NotNull ProgressIndicator indicator) {
Set<PluginNode> dependant = new THashSet<PluginNode>();
boolean install = prepareToInstall(pluginsToInstall, allPlugins, dependant, indicator);
for (PluginNode node : dependant) {
if (!pluginsToInstall.contains(node)) {
pluginsToInstall.add(node);
@@ -54,21 +60,18 @@ public class PluginInstaller {
private static boolean prepareToInstall(List<PluginNode> pluginsToInstall,
List<IdeaPluginDescriptor> allPlugins,
Set<PluginNode> installedDependant) {
ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator();
final List<PluginId> pluginIds = new ArrayList<PluginId>();
Set<PluginNode> installedDependant,
@NotNull ProgressIndicator progressIndicator) {
List<PluginId> pluginIds = new SmartList<PluginId>();
for (PluginNode pluginNode : pluginsToInstall) {
pluginIds.add(pluginNode.getPluginId());
}
boolean result = false;
for (final PluginNode pluginNode : pluginsToInstall) {
if (pi != null) pi.setText(pluginNode.getName());
for (PluginNode pluginNode : pluginsToInstall) {
progressIndicator.setText(pluginNode.getName());
try {
result |= prepareToInstall(pluginNode, pluginIds, allPlugins, installedDependant);
result |= prepareToInstall(pluginNode, pluginIds, allPlugins, installedDependant, progressIndicator);
}
catch (IOException e) {
String title = IdeBundle.message("title.plugin.error");
@@ -83,7 +86,8 @@ public class PluginInstaller {
private static boolean prepareToInstall(final PluginNode pluginNode,
final List<PluginId> pluginIds,
List<IdeaPluginDescriptor> allPlugins,
Set<PluginNode> installedDependant) throws IOException {
Set<PluginNode> installedDependant,
@NotNull ProgressIndicator progressIndicator) throws IOException {
installedDependant.add(pluginNode);
// check for dependent plugins at first.
if (pluginNode.getDepends() != null && pluginNode.getDepends().size() > 0) {
@@ -93,7 +97,6 @@ public class PluginInstaller {
final List<PluginNode> optionalDeps = new ArrayList<PluginNode>();
for (int i = 0; i < pluginNode.getDepends().size(); i++) {
PluginId depPluginId = pluginNode.getDepends().get(i);
if (PluginManager.isPluginInstalled(depPluginId) || PluginManagerCore.isModuleDependency(depPluginId) ||
PluginManagerUISettings.getInstance().getInstalledPlugins().contains(depPluginId.getIdString()) ||
(pluginIds != null && pluginIds.contains(depPluginId))) {
@@ -123,6 +126,7 @@ public class PluginInstaller {
}
try {
GuiUtils.runOrInvokeAndWait(new Runnable() {
@Override
public void run() {
String title = IdeBundle.message("plugin.manager.dependencies.detected.title");
String message = IdeBundle.message("plugin.manager.dependencies.detected.message", depends.size(), buf.substring(0, buf.length() - 1));
@@ -134,7 +138,7 @@ public class PluginInstaller {
return false;
}
if (proceed[0]) {
if (!prepareToInstall(depends, allPlugins, installedDependant)) {
if (!prepareToInstall(depends, allPlugins, installedDependant, progressIndicator)) {
return false;
}
}
@@ -151,6 +155,7 @@ public class PluginInstaller {
final boolean[] proceed = new boolean[1];
try {
GuiUtils.runOrInvokeAndWait(new Runnable() {
@Override
public void run() {
proceed[0] =
Messages.showYesNoDialog(IdeBundle.message("plugin.manager.optional.dependencies.detected.message", optionalDeps.size(),
@@ -164,19 +169,19 @@ public class PluginInstaller {
return false;
}
if (proceed[0]) {
if (!prepareToInstall(optionalDeps, allPlugins, installedDependant)) {
if (!prepareToInstall(optionalDeps, allPlugins, installedDependant, progressIndicator)) {
return false;
}
}
}
}
PluginDownloader downloader = null;
PluginDownloader downloader;
final String repositoryName = pluginNode.getRepositoryName();
if (repositoryName != null) {
try {
final Map<PluginId, PluginDownloader> downloaders = new HashMap<PluginId, PluginDownloader>();
if (!UpdateChecker.checkPluginsHost(repositoryName, downloaders)) {
Map<PluginId, PluginDownloader> downloaders = new THashMap<PluginId, PluginDownloader>();
if (!UpdateChecker.checkPluginsHost(repositoryName, downloaders, progressIndicator)) {
return false;
}
downloader = downloaders.get(pluginNode.getPluginId());
@@ -190,7 +195,7 @@ public class PluginInstaller {
downloader = PluginDownloader.createDownloader(pluginNode);
}
if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) {
if (downloader.prepareToInstall(progressIndicator)) {
synchronized (myLock) {
downloader.install();
}
@@ -199,7 +204,6 @@ public class PluginInstaller {
else {
return false;
}
return true;
}
@@ -415,7 +415,7 @@ public abstract class PluginManagerMain implements Disposable {
@Override
public void run(@NotNull ProgressIndicator indicator) {
try {
if (PluginInstaller.prepareToInstall(plugins, allPlugins)) {
if (PluginInstaller.prepareToInstall(plugins, allPlugins, indicator)) {
ApplicationManager.getApplication().invokeLater(onSuccess);
result[0] = true;
}
@@ -24,10 +24,14 @@ import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.util.PathUtil;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.net.NetUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.xml.parsers.SAXParser;
@@ -35,6 +39,7 @@ import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.zip.GZIPInputStream;
@@ -49,8 +54,70 @@ public class RepositoryHelper {
return loadPluginsFromRepository(indicator, null);
}
public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable ProgressIndicator indicator,
BuildNumber buildnumber) throws Exception {
@NotNull
public static Pair<URLConnection, String> openConnection(@NotNull String initialUrl, boolean supportGzip) throws IOException {
int i = 0;
String url = initialUrl;
while (i++ < 99) {
URLConnection connection;
if (ApplicationManager.getApplication() != null) {
connection = HttpConfigurable.getInstance().openConnection(url);
}
else {
connection = new URL(url).openConnection();
connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
}
if (supportGzip) {
connection.setRequestProperty("Accept-Encoding", "gzip");
}
connection.setUseCaches(false);
if (connection instanceof HttpURLConnection) {
int responseCode = ((HttpURLConnection)connection).getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK && responseCode != HttpURLConnection.HTTP_NOT_MODIFIED) {
if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
url = connection.getHeaderField("Location");
}
else {
url = null;
}
if (url == null) {
throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode));
}
else {
((HttpURLConnection)connection).disconnect();
continue;
}
}
}
return Pair.create(connection, url == initialUrl ? null : url);
}
throw new IOException("Infinite redirection");
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
@NotNull
public static InputStream getConnectionInputStream(@NotNull URLConnection connection) throws IOException {
InputStream inputStream = connection.getInputStream();
if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) {
try {
return new GZIPInputStream(inputStream);
}
catch (IOException e) {
inputStream.close();
throw e;
}
}
else {
return inputStream;
}
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable ProgressIndicator indicator, @Nullable BuildNumber buildnumber) throws Exception {
ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance();
String url = appInfo.getPluginsListUrl() + "?build=" + (buildnumber != null ? buildnumber.asString() : appInfo.getApiVersion());
@@ -70,17 +137,10 @@ public class RepositoryHelper {
}
}
HttpURLConnection connection = ApplicationManager.getApplication() != null ?
HttpConfigurable.getInstance().openHttpConnection(url) :
(HttpURLConnection)new URL(url).openConnection();
connection.setRequestProperty("Accept-Encoding", "gzip");
connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
HttpURLConnection connection = (HttpURLConnection)openConnection(url, true).first;
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
}
connection.connect();
try {
if (indicator != null) {
@@ -91,49 +151,35 @@ public class RepositoryHelper {
return loadPluginList(pluginListFile);
}
String encoding = connection.getContentEncoding();
InputStream is = connection.getInputStream();
try {
if ("gzip".equalsIgnoreCase(encoding)) {
is = new GZIPInputStream(is);
}
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.downloading.list.of.plugins"));
}
return readPluginsStream(is, indicator, PLUGIN_LIST_FILE);
}
finally {
is.close();
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.downloading.list.of.plugins"));
}
return readPluginsStream(connection, indicator, PLUGIN_LIST_FILE);
}
finally {
connection.disconnect();
}
}
private synchronized static List<IdeaPluginDescriptor> readPluginsStream(InputStream is,
private synchronized static List<IdeaPluginDescriptor> readPluginsStream(@NotNull URLConnection connection,
ProgressIndicator indicator,
String file) throws Exception {
File temp = createLocalPluginsDescriptions(file);
OutputStream os = new FileOutputStream(temp, false);
@NotNull String file) throws Exception {
File localFile;
InputStream input = getConnectionInputStream(connection);
try {
byte[] buffer = new byte[1024];
int size;
while ((size = is.read(buffer)) > 0) {
os.write(buffer, 0, size);
if (indicator != null) {
indicator.checkCanceled();
}
localFile = createLocalPluginsDescriptions(file);
OutputStream output = new FileOutputStream(localFile);
try {
NetUtils.copyStreamContent(indicator, input, output, connection.getContentLength());
}
finally {
output.close();
}
}
finally {
os.close();
input.close();
}
return loadPluginList(temp);
return loadPluginList(localFile);
}
private static List<IdeaPluginDescriptor> loadPluginList(File file) throws Exception {
@@ -143,7 +189,8 @@ public class RepositoryHelper {
return handler.getPluginsList();
}
private static File createLocalPluginsDescriptions(String file) throws IOException {
@NotNull
private static File createLocalPluginsDescriptions(@NotNull String file) throws IOException {
File basePath = new File(PathManager.getPluginsPath());
if (!basePath.isDirectory() && !basePath.mkdirs()) {
throw new IOException("Cannot create directory: " + basePath);
@@ -153,17 +200,14 @@ public class RepositoryHelper {
if (temp.exists()) {
FileUtil.delete(temp);
}
FileUtil.createIfDoesntExist(temp);
else {
FileUtilRt.createParentDirs(temp);
}
return temp;
}
public static List<IdeaPluginDescriptor> loadPluginsFromDescription(InputStream is, ProgressIndicator indicator) throws Exception {
try {
return readPluginsStream(is, indicator, "host.xml");
}
finally {
is.close();
}
public static List<IdeaPluginDescriptor> loadPluginsFromDescription(@NotNull URLConnection connection, @Nullable ProgressIndicator indicator) throws Exception {
return readPluginsStream(connection, indicator, "host.xml");
}
public static String getDownloadUrl() {
@@ -498,14 +498,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
private ActionCallback initConfigurable(@NotNull final Configurable configurable) {
final ActionCallback result = new ActionCallback();
final ConfigurableContent content;
if (configurable instanceof MasterDetails) {
content = new Details((MasterDetails)configurable);
}
else {
content = new Simple(configurable);
}
final ConfigurableContent content = new Simple(configurable);
if (!myConfigurable2Content.containsKey(configurable)) {
if (configurable instanceof Place.Navigator) {
@@ -1068,7 +1061,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
@Override
void set(final ContentWrapper wrapper) {
myOwnDetails.setDetailsModeEnabled(true);
wrapper.setContent(myComponent, getContext().getErrors().get(myConfigurable), !ConfigurableWrapper.isNoScroll(myConfigurable));
boolean noScroll = ConfigurableWrapper.isNoScroll(myConfigurable) ||
ConfigurableWrapper.cast(MasterDetails.class, myConfigurable) != null;
wrapper.setContent(myComponent, getContext().getErrors().get(myConfigurable), !noScroll);
}
@Override
@@ -26,6 +26,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -34,7 +35,6 @@ import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.util.PathUtil;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.io.ZipUtil;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.net.NetUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -42,7 +42,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
@@ -262,15 +261,10 @@ public class PluginDownloader {
if (ApplicationManager.getApplication() != null && pi != null) {
pi.setText(IdeBundle.message("progress.downloading.plugin", getPluginName()));
}
final int contentLength = connection.getContentLength();
if (pi != null) {
pi.setIndeterminate(contentLength == -1);
}
try {
final OutputStream fos = new BufferedOutputStream(new FileOutputStream(file, false));
try {
NetUtils.copyStreamContent(pi, is, fos, contentLength);
NetUtils.copyStreamContent(pi, is, fos, connection.getContentLength());
}
finally {
fos.close();
@@ -295,34 +289,12 @@ public class PluginDownloader {
}
}
private URLConnection openConnection(final String url) throws IOException {
final URLConnection connection;
if (ApplicationManager.getApplication() != null) {
connection = HttpConfigurable.getInstance().openConnection(url);
private URLConnection openConnection(@NotNull String url) throws IOException {
Pair<URLConnection, String> result = RepositoryHelper.openConnection(url, false);
if (result.second != null) {
myPluginUrl = result.second;
}
else {
connection = new URL(url).openConnection();
connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
}
if (connection instanceof HttpURLConnection) {
final int responseCode = ((HttpURLConnection)connection).getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
String location = null;
if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
location = connection.getHeaderField("Location");
}
if (location == null) {
throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode));
}
else {
myPluginUrl = location;
((HttpURLConnection)connection).disconnect();
return openConnection(location);
}
}
}
return connection;
return result.first;
}
@NotNull
@@ -334,9 +334,9 @@ public final class UpdateChecker {
return hosts;
}
public static boolean checkPluginsHost(final String host, final Map<PluginId, PluginDownloader> downloaded) throws Exception {
public static boolean checkPluginsHost(final String host, final Map<PluginId, PluginDownloader> downloaded, @NotNull ProgressIndicator progressIndicator) throws Exception {
try {
return checkPluginsHost(host, downloaded, null, true, null, null);
return checkPluginsHost(host, downloaded, null, true, progressIndicator, null);
}
catch (ProcessCanceledException e) {
return false;
@@ -356,19 +356,15 @@ public final class UpdateChecker {
final boolean collectToUpdate,
final @Nullable ProgressIndicator indicator,
final BuildNumber buildNumber) throws Exception {
InputStream inputStream = loadVersionInfo(host);
if (inputStream == null) return false;
final Document document;
try {
document = JDOMUtil.loadDocument(inputStream);
document = JDOMUtil.loadDocument(RepositoryHelper.getConnectionInputStream(loadVersionInfo(host)));
}
catch (JDOMException e) {
return false;
}
inputStream = loadVersionInfo(host);
if (inputStream == null) return false;
final List<IdeaPluginDescriptor> descriptors = RepositoryHelper.loadPluginsFromDescription(inputStream, indicator);
final List<IdeaPluginDescriptor> descriptors = RepositoryHelper.loadPluginsFromDescription(loadVersionInfo(host), indicator);
for (IdeaPluginDescriptor descriptor : descriptors) {
((PluginNode)descriptor).setRepositoryName(host);
prepareToInstall(PluginDownloader.createDownloader(descriptor, buildNumber), buildNumber, downloaded, incompatiblePlugins, collectToUpdate,
@@ -412,29 +408,19 @@ public final class UpdateChecker {
if (collectToUpdate) {
final String finalPluginUrl = getPluginUrl(pluginFile);
final Runnable updatePluginRunnable = new Runnable() {
public void run() {
try {
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
if (progressIndicator != null) {
progressIndicator.setText2(finalPluginUrl);
}
final PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null, buildNumber);
prepareToInstall(downloader, buildNumber, downloaded, incompatiblePlugins, collectToUpdate, indicator);
}
catch (IOException e) {
LOG.info(e);
}
}
};
if (ApplicationManager.getApplication().isDispatchThread()) {
String title = IdeBundle.message("update.uploading.plugin.progress.title");
ProgressManager.getInstance().runProcessWithProgressSynchronously(updatePluginRunnable, title, true, null);
ProgressManager.getInstance().run(new Task.Modal(null, IdeBundle.message("update.uploading.plugin.progress.title"), true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
updatePlugins(finalPluginUrl, pluginId, pluginVersion, buildNumber, downloaded, incompatiblePlugins, true, indicator);
}
});
}
else {
updatePluginRunnable.run();
updatePlugins(finalPluginUrl, pluginId, pluginVersion, buildNumber, downloaded, incompatiblePlugins, true, indicator);
}
} else {
}
else {
final PluginDownloader downloader = new PluginDownloader(pluginId, pluginUrl, pluginVersion);
downloader.setDescription(description);
downloader.setDepends(dependsPlugins);
@@ -444,6 +430,24 @@ public final class UpdateChecker {
return success;
}
private static void updatePlugins(String finalPluginUrl,
String pluginId,
String pluginVersion,
BuildNumber buildNumber,
Map<PluginId, PluginDownloader> downloaded,
Collection<IdeaPluginDescriptor> incompatiblePlugins, boolean collectToUpdate, ProgressIndicator indicator) {
try {
if (indicator != null) {
indicator.setText2(finalPluginUrl);
}
PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null, buildNumber);
prepareToInstall(downloader, buildNumber, downloaded, incompatiblePlugins, collectToUpdate, indicator);
}
catch (IOException e) {
LOG.info(e);
}
}
@NotNull
private static String getPluginUrl(@NotNull VirtualFile pluginFile) {
String protocol = pluginFile.getFileSystem().getProtocol();
@@ -502,6 +506,7 @@ public final class UpdateChecker {
if (newChannelReady(channelToPropose)) {
Runnable runnable = new Runnable() {
@Override
public void run() {
new NewChannelDialog(channelToPropose).show();
}
@@ -606,34 +611,28 @@ public final class UpdateChecker {
}
}
private static InputStream loadVersionInfo(final String url) throws Exception {
final InputStream[] inputStreams = new InputStream[]{null};
final Exception[] exception = new Exception[]{null};
@NotNull
private static URLConnection loadVersionInfo(@NotNull final String url) throws Exception {
final Ref<URLConnection> connectionRef = Ref.create();
final Ref<Exception> exception = Ref.create();
Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {
final String urlToCheck;
String urlToCheck;
if (!StandardFileSystems.FILE_PROTOCOL.equals(new URL(url).getProtocol())) {
urlToCheck = url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString();
} else {
}
else {
urlToCheck = url;
}
URLConnection connection;
if (ApplicationManager.getApplication() != null) {
connection = HttpConfigurable.getInstance().openConnection(urlToCheck);
}
else {
connection = new URL(urlToCheck).openConnection();
connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
}
URLConnection connection = RepositoryHelper.openConnection(urlToCheck, true).first;
connection.connect();
inputStreams[0] = connection.getInputStream();
connectionRef.set(connection);
}
catch (IOException e) {
exception[0] = e;
exception.set(e);
}
}
});
@@ -641,15 +640,18 @@ public final class UpdateChecker {
try {
downloadThreadFuture.get(5, TimeUnit.SECONDS);
}
catch (TimeoutException ignored) { }
catch (TimeoutException ignored) {
}
if (!downloadThreadFuture.isDone()) {
downloadThreadFuture.cancel(true);
throw new ConnectionException(IdeBundle.message("updates.timeout.error"));
}
if (exception[0] != null) throw exception[0];
return inputStreams[0];
if (!exception.isNull()) {
throw exception.get();
}
return connectionRef.get();
}
public static String getInstallationUID(final PropertiesComponent propertiesComponent) {
@@ -734,6 +736,7 @@ public final class UpdateChecker {
final DownloadPatchResult[] result = new DownloadPatchResult[]{DownloadPatchResult.CANCELED};
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
try {
doDownloadAndInstallPatch(newVersion, ProgressManager.getInstance().getProgressIndicator());
@@ -448,3 +448,5 @@ new.css.schema.enabled=true
editor.disable.rtl=false
editor.disable.rtl.description=Disables RTL support in editor (which is broken now anyway)
decompiler.use.line.table=false
@@ -36,6 +36,7 @@ import org.jetbrains.annotations.Nullable;
* @deprecated to remove in IDEA 15
*/
@Deprecated
@SuppressWarnings("UnusedDeclaration")
@State(
name = "VcsManagerConfiguration",
storages = @Storage(file = StoragePathMacros.MODULE_FILE)
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,10 +60,25 @@ public class FloatingPointEqualityInspection extends BaseInspection {
if (!TypeUtils.hasFloatingPointType(lhs) && !TypeUtils.hasFloatingPointType(rhs)) {
return;
}
if (ExpressionUtils.isZero(lhs) || ExpressionUtils.isZero(rhs)) {
if (isInfinityOrZero(lhs) || isInfinityOrZero(rhs)) {
return;
}
registerError(expression);
}
private static boolean isInfinityOrZero(PsiExpression expression) {
final Object value = ExpressionUtils.computeConstantExpression(expression);
if (value instanceof Double) {
final Double aDouble = (Double)value;
final double v = aDouble.doubleValue();
return v == Double.NEGATIVE_INFINITY || v == Double.POSITIVE_INFINITY || v == 0.0;
}
else if (value instanceof Float) {
final Float aFloat = (Float)value;
final float f = aFloat.floatValue();
return f == Float.NEGATIVE_INFINITY || f == Float.POSITIVE_INFINITY || f == 0.0f;
}
return false;
}
}
}
@@ -1,10 +1,10 @@
<html>
<body>
Reports floating-point values
being compared with <b>==</b> or <b>!=</b>.
being compared with an <b>==</b> or <b>!=</b> operator.
Floating point values are inherently inaccurate, and comparing them for exact
equality is almost never the desired semantics. This inspection ignores comparisons
with zero literals.
with zero and infinity literals.
<!-- tooltip end -->
<p>
@@ -1,36 +0,0 @@
package com.siyeh.igtest.bugs;
public class FloatingPointEqualityInspection
{
private double m_bar;
private double m_baz;
private float m_barf;
private float m_bazf;
public static final float TENTH = 0.1f;
public static final float fifth = 0.2f;
public FloatingPointEqualityInspection()
{
m_bar = 0.0;
m_baz = 1.0;
m_barf = TENTH;
m_bazf = fifth;
}
public void foo()
{
if (m_bar == m_baz) {
System.out.println("m_bar = " + m_bar);
}
if (m_barf == m_bazf) {
System.out.println("m_barf = " + m_barf);
}
if (m_barf != m_bar) {
System.out.println("m_barf = " + m_barf);
}
}
}
@@ -0,0 +1,38 @@
public class FloatingPointEquality
{
private double m_bar;
private double m_baz;
private float m_barf;
private float m_bazf;
public static final float TENTH = 0.1f;
public static final float fifth = 0.2f;
public FloatingPointEquality()
{
m_bar = 0.0;
m_baz = 1.0;
m_barf = TENTH;
m_bazf = fifth;
}
public void foo()
{
if (<warning descr="'m_bar == m_baz': floating point values compared for exact equality">m_bar == m_baz</warning>) {
System.out.println("m_bar = " + m_bar);
}
if (<warning descr="'m_barf == m_bazf': floating point values compared for exact equality">m_barf == m_bazf</warning>) {
System.out.println("m_barf = " + m_barf);
}
if (<warning descr="'m_barf != m_bar': floating point values compared for exact equality">m_barf != m_bar</warning>) {
System.out.println("m_barf = " + m_barf);
}
boolean infinity = m_bar == Double.POSITIVE_INFINITY;
boolean zero = m_barf == 0.0f;
}
}
@@ -0,0 +1,35 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.numeric;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import junit.framework.TestCase;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class FloatingPointEqualityInspectionTest extends LightInspectionTestCase {
public void testFloatingPointEquality() { doTest(); }
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new FloatingPointEqualityInspection();
}
}
@@ -22,11 +22,11 @@ import org.jetbrains.annotations.NotNull;
*/
public final class GitPushTagMode implements VcsPushOptionValue {
public static GitPushTagMode ALL = new GitPushTagMode("All", "--tags");
public static GitPushTagMode FOLLOW = new GitPushTagMode("Current Branch", "--follow-tags");
public static final GitPushTagMode ALL = new GitPushTagMode("All", "--tags");
public static final GitPushTagMode FOLLOW = new GitPushTagMode("Current Branch", "--follow-tags");
@NotNull private final String myTitle;
@NotNull private final String myArgument;
@NotNull private String myTitle;
@NotNull private String myArgument;
// for deserialization
@SuppressWarnings("UnusedDeclaration")
@@ -54,6 +54,18 @@ public final class GitPushTagMode implements VcsPushOptionValue {
return myArgument;
}
// for deserialization
@SuppressWarnings("UnusedDeclaration")
public void setTitle(@NotNull String title) {
myTitle = title;
}
// for deserialization
@SuppressWarnings("UnusedDeclaration")
public void setArgument(@NotNull String argument) {
myArgument = argument;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -33,7 +33,7 @@ class GitPushTagPanel extends VcsPushOptionsPanel {
private final ComboBox myCombobox;
private final JBCheckBox myCheckBox;
GitPushTagPanel(@Nullable GitPushTagMode defaultMode, boolean followTagsSupported) {
GitPushTagPanel(@NotNull GitPushTagMode defaultMode, boolean followTagsSupported) {
String checkboxText = "Push Tags";
if (followTagsSupported) {
checkboxText += ": ";
@@ -76,7 +76,7 @@ public class ClassWriter {
}
}
public void classLambdaToJava(ClassNode node, StringBuilder buffer, Exprent method_object, int indent) {
public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_object, int indent) {
// get the class node with the content method
ClassNode classNode = node;
while (classNode != null && classNode.type == ClassNode.CLASS_LAMBDA) {
@@ -149,8 +149,7 @@ public class ClassWriter {
methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer);
InterpreterUtil.appendIndent(buffer, indent);
buffer.append("}");
buffer.appendIndent(indent).append("}");
}
}
finally {
@@ -160,7 +159,7 @@ public class ClassWriter {
DecompilerContext.getLogger().endWriteClass();
}
public void classToJava(ClassNode node, StringBuilder buffer, int indent) {
public void classToJava(ClassNode node, TextBuffer buffer, int indent) {
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
@@ -265,8 +264,7 @@ public class ClassWriter {
}
}
InterpreterUtil.appendIndent(buffer, indent);
buffer.append('}');
buffer.appendIndent(indent).append('}');
if (node.type != ClassNode.CLASS_ANONYMOUS) {
buffer.append(lineSeparator);
@@ -279,9 +277,8 @@ public class ClassWriter {
DecompilerContext.getLogger().endWriteClass();
}
private void writeClassDefinition(ClassNode node, StringBuilder buffer, int indent) {
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) {
String lineSeparator = DecompilerContext.getNewLineSeparator();
String indentString = InterpreterUtil.getIndentString(indent);
if (node.type == ClassNode.CLASS_ANONYMOUS) {
buffer.append(" {");
@@ -300,7 +297,7 @@ public class ClassWriter {
boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0;
if (isDeprecated) {
appendDeprecation(buffer, indentString, lineSeparator);
appendDeprecation(buffer, indent, lineSeparator);
}
if (interceptor != null) {
@@ -309,12 +306,12 @@ public class ClassWriter {
}
if (isSynthetic) {
appendComment(buffer, "synthetic class", indentString, lineSeparator);
appendComment(buffer, "synthetic class", indent, lineSeparator);
}
appendAnnotations(buffer, cl, indent, lineSeparator);
buffer.append(indentString);
buffer.appendIndent(indent);
if (isEnum) {
// remove abstract and final flags (JLS 8.9 Enums)
@@ -390,8 +387,7 @@ public class ClassWriter {
buffer.append(lineSeparator);
}
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, StringBuilder buffer, int indent, BytecodeMappingTracer tracer) {
String indentString = InterpreterUtil.getIndentString(indent);
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
String lineSeparator = DecompilerContext.getNewLineSeparator();
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
@@ -399,7 +395,7 @@ public class ClassWriter {
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
if (isDeprecated) {
appendDeprecation(buffer, indentString, lineSeparator);
appendDeprecation(buffer, indent, lineSeparator);
}
if (interceptor != null) {
@@ -408,12 +404,12 @@ public class ClassWriter {
}
if (fd.isSynthetic()) {
appendComment(buffer, "synthetic field", indentString, lineSeparator);
appendComment(buffer, "synthetic field", indent, lineSeparator);
}
appendAnnotations(buffer, fd, indent, lineSeparator);
buffer.append(indentString);
buffer.appendIndent(indent);
if (!isEnum) {
appendModifiers(buffer, fd.getAccessFlags(), FIELD_ALLOWED, isInterface, FIELD_EXCLUDED);
@@ -479,7 +475,7 @@ public class ClassWriter {
private static void methodLambdaToJava(ClassNode lambdaNode,
ClassNode classNode,
StructMethod mt,
StringBuilder buffer,
TextBuffer buffer,
int indent,
boolean codeOnly, BytecodeMappingTracer tracer) {
ClassWrapper classWrapper = classNode.wrapper;
@@ -494,7 +490,7 @@ public class ClassWriter {
MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(lambdaNode.lambda_information.method_descriptor);
if (!codeOnly) {
InterpreterUtil.appendIndent(buffer, indent);
buffer.appendIndent(indent);
buffer.append("public ");
buffer.append(method_name);
buffer.append("(");
@@ -547,7 +543,7 @@ public class ClassWriter {
}
if (methodWrapper.decompiledWithErrors) {
InterpreterUtil.appendIndent(buffer, indent);
buffer.appendIndent(indent);
buffer.append("// $FF: Couldn't be decompiled");
buffer.append(DecompilerContext.getNewLineSeparator());
}
@@ -555,7 +551,7 @@ public class ClassWriter {
if (!codeOnly) {
indent -= 1;
InterpreterUtil.appendIndent(buffer, indent);
buffer.appendIndent(indent);
buffer.append('}');
buffer.append(DecompilerContext.getNewLineSeparator());
}
@@ -565,7 +561,7 @@ public class ClassWriter {
}
}
private boolean methodToJava(ClassNode node, StructMethod mt, StringBuilder buffer, int indent, BytecodeMappingTracer tracer) {
private boolean methodToJava(ClassNode node, StructMethod mt, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
ClassWrapper wrapper = node.wrapper;
StructClass cl = wrapper.getClassStruct();
MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
@@ -573,7 +569,6 @@ public class ClassWriter {
boolean hideMethod = false;
int start_index_method = buffer.length();
String indentString = InterpreterUtil.getIndentString(indent);
String lineSeparator = DecompilerContext.getNewLineSeparator();
MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
@@ -586,6 +581,15 @@ public class ClassWriter {
boolean isDeprecated = mt.getAttributes().containsKey("Deprecated");
boolean clinit = false, init = false, dinit = false;
int startLine = -1;
if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) {
StructLineNumberTableAttribute lineNumberTable =
(StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
if (lineNumberTable != null) {
startLine = lineNumberTable.getFirstLine();
}
}
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
int flags = mt.getAccessFlags();
@@ -597,7 +601,7 @@ public class ClassWriter {
}
if (isDeprecated) {
appendDeprecation(buffer, indentString, lineSeparator);
appendDeprecation(buffer, indent, lineSeparator);
}
if (interceptor != null) {
@@ -608,15 +612,15 @@ public class ClassWriter {
boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic");
boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0;
if (isSynthetic) {
appendComment(buffer, "synthetic method", indentString, lineSeparator);
appendComment(buffer, "synthetic method", indent, lineSeparator);
}
if (isBridge) {
appendComment(buffer, "bridge method", indentString, lineSeparator);
appendComment(buffer, "bridge method", indent, lineSeparator);
}
appendAnnotations(buffer, mt, indent, lineSeparator);
buffer.append(indentString);
buffer.appendIndent(indent);
appendModifiers(buffer, flags, METHOD_ALLOWED, isInterface, METHOD_EXCLUDED);
@@ -800,8 +804,9 @@ public class ClassWriter {
buffer.append(' ');
}
buffer.append('{');
buffer.append(lineSeparator);
//TODO: for now only start line set
buffer.setCurrentLine(startLine);
buffer.append('{').appendLineSeparator();
RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
@@ -823,14 +828,12 @@ public class ClassWriter {
}
if (methodWrapper.decompiledWithErrors) {
buffer.append(InterpreterUtil.getIndentString(indent + 1));
buffer.appendIndent(indent + 1);
buffer.append("// $FF: Couldn't be decompiled");
buffer.append(lineSeparator);
}
buffer.append(indentString);
buffer.append('}');
buffer.append(lineSeparator);
buffer.appendIndent(indent).append('}').appendLineSeparator();
}
}
finally {
@@ -861,16 +864,16 @@ public class ClassWriter {
return true;
}
private static void appendDeprecation(StringBuilder buffer, String indentString, String lineSeparator) {
buffer.append(indentString).append("/** @deprecated */").append(lineSeparator);
private static void appendDeprecation(TextBuffer buffer, int indent, String lineSeparator) {
buffer.appendIndent(indent).append("/** @deprecated */").append(lineSeparator);
}
private enum MType {CLASS, FIELD, METHOD}
private static void appendRenameComment(StringBuilder buffer, String oldName, MType type, int indent, String lineSeparator) {
private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent, String lineSeparator) {
if (oldName == null) return;
InterpreterUtil.appendIndent(buffer, indent);
buffer.appendIndent(indent);
buffer.append("// $FF: renamed from: ");
switch (type) {
@@ -915,14 +918,14 @@ public class ClassWriter {
return typeText;
}
private static void appendComment(StringBuilder buffer, String comment, String indentString, String lineSeparator) {
buffer.append(indentString).append("// $FF: ").append(comment).append(lineSeparator);
private static void appendComment(TextBuffer buffer, String comment, int indent, String lineSeparator) {
buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator);
}
private static final String[] ANNOTATION_ATTRIBUTES = {
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
private static void appendAnnotations(StringBuilder buffer, StructMember mb, int indent, String lineSeparator) {
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent, String lineSeparator) {
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
@@ -939,7 +942,7 @@ public class ClassWriter {
private static final String[] PARAMETER_ANNOTATION_ATTRIBUTES = {
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
private static void appendParameterAnnotations(StringBuilder buffer, StructMethod mt, int param) {
private static void appendParameterAnnotations(TextBuffer buffer, StructMethod mt, int param) {
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
@@ -984,7 +987,7 @@ public class ClassWriter {
private static final int FIELD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL;
private static final int METHOD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_ABSTRACT;
private static void appendModifiers(StringBuilder buffer, int flags, int allowed, boolean isInterface, int excluded) {
private static void appendModifiers(TextBuffer buffer, int flags, int allowed, boolean isInterface, int excluded) {
flags &= allowed;
if (!isInterface) excluded = 0;
for (int modifier : MODIFIERS.keySet()) {
@@ -994,7 +997,7 @@ public class ClassWriter {
}
}
private static void appendTypeParameters(StringBuilder buffer, List<String> parameters, List<List<GenericType>> bounds) {
private static void appendTypeParameters(TextBuffer buffer, List<String> parameters, List<List<GenericType>> bounds) {
buffer.append('<');
for (int i = 0; i < parameters.size(); i++) {
@@ -236,7 +236,7 @@ public class ClassesProcessor {
}
}
public void writeClass(StructClass cl, StringBuilder buffer) throws IOException {
public void writeClass(StructClass cl, TextBuffer buffer) throws IOException {
ClassNode root = mapRootClasses.get(cl.qualifiedName);
if (root.type != ClassNode.CLASS_ROOT) {
return;
@@ -260,7 +260,7 @@ public class ClassesProcessor {
new NestedMemberAccess().propagateMemberAccess(root);
StringBuilder classBuffer = new StringBuilder(AVERAGE_CLASS_SIZE);
TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
new ClassWriter().classToJava(root, classBuffer, 0);
String lineSeparator = DecompilerContext.getNewLineSeparator();
@@ -80,11 +80,11 @@ public class Fernflower implements IDecompiledData {
}
@Override
public String getClassContent(StructClass cl) {
public TextBuffer getClassContent(StructClass cl) {
try {
StringBuilder buffer = new StringBuilder(ClassesProcessor.AVERAGE_CLASS_SIZE);
TextBuffer buffer = new TextBuffer(ClassesProcessor.AVERAGE_CLASS_SIZE);
classesProcessor.writeClass(cl, buffer);
return buffer.toString();
return buffer;
}
catch (Throwable ex) {
DecompilerContext.getLogger().writeMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled.", ex);
@@ -0,0 +1,175 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import java.util.*;
/**
* Allows to connect text with resulting lines
*
* @author egor
*/
public class TextBuffer {
private final String myLineSeparator = DecompilerContext.getNewLineSeparator();
private final String myIndent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING);
private final StringBuilder myStringBuilder;
private Map<Integer, Integer> myLineToOffsetMapping = null;
public TextBuffer() {
myStringBuilder = new StringBuilder();
}
public TextBuffer(int size) {
myStringBuilder = new StringBuilder(size);
}
public void setCurrentLine(int line) {
if (line >= 0) {
checkMapCreated();
myLineToOffsetMapping.put(line, myStringBuilder.length()+1);
}
}
public TextBuffer append(String str) {
myStringBuilder.append(str);
return this;
}
public TextBuffer append(char ch) {
myStringBuilder.append(ch);
return this;
}
public TextBuffer appendLineSeparator() {
myStringBuilder.append(myLineSeparator);
return this;
}
public TextBuffer appendIndent(int length) {
while (length-- > 0) {
append(myIndent);
}
return this;
}
public TextBuffer addBanner(String banner) {
myStringBuilder.insert(0, banner);
if (myLineToOffsetMapping != null) {
for (Integer line : myLineToOffsetMapping.keySet()) {
myLineToOffsetMapping.put(line, myLineToOffsetMapping.get(line) + banner.length());
}
}
return this;
}
@Override
public String toString() {
String original = myStringBuilder.toString();
if (myLineToOffsetMapping == null || myLineToOffsetMapping.isEmpty()) {
return original;
}
else {
StringBuilder res = new StringBuilder();
String[] srcLines = original.split(myLineSeparator);
int currentLineStartOffset = 0;
int currentLine = 0;
int previousMarkLine = 0;
int dumpedLines = 0;
ArrayList<Integer> linesWithMarks = new ArrayList<Integer>(myLineToOffsetMapping.keySet());
Collections.sort(linesWithMarks);
for (Integer markLine : linesWithMarks) {
Integer markOffset = myLineToOffsetMapping.get(markLine);
while (currentLine < srcLines.length) {
String line = srcLines[currentLine];
int lineEnd = currentLineStartOffset + line.length() + myLineSeparator.length();
if (markOffset >= currentLineStartOffset && markOffset <= lineEnd) {
int requiredLinesNumber = markLine - dumpedLines;
dumpedLines = markLine;
appendLines(res, srcLines, previousMarkLine, currentLine, requiredLinesNumber);
previousMarkLine = currentLine;
break;
}
currentLineStartOffset = lineEnd;
currentLine++;
}
}
if (previousMarkLine < srcLines.length) {
appendLines(res, srcLines, previousMarkLine, srcLines.length, srcLines.length - previousMarkLine);
}
return res.toString();
}
}
private void appendLines(StringBuilder res, String[] srcLines, int from, int to, int requiredLineNumber) {
if (to - from > requiredLineNumber) {
int separatorsRequired = to - from - requiredLineNumber - 1;
for (int i = from; i < to; i++) {
res.append(srcLines[i]);
if (separatorsRequired-- > 0) {
res.append(myLineSeparator);
}
}
res.append(myLineSeparator);
}
else if (to - from <= requiredLineNumber) {
for (int i = from; i < to; i++) {
res.append(srcLines[i]).append(myLineSeparator);
}
for (int i = 0; i < requiredLineNumber - to + from; i++) {
res.append(myLineSeparator);
}
}
}
public int length() {
return myStringBuilder.length();
}
public String substring(int start) {
return myStringBuilder.substring(start);
}
public void setLength(int position) {
myStringBuilder.setLength(position);
}
public TextBuffer append(TextBuffer buffer) {
if (buffer.myLineToOffsetMapping != null && !buffer.myLineToOffsetMapping.isEmpty()) {
checkMapCreated();
for (Map.Entry<Integer, Integer> entry : buffer.myLineToOffsetMapping.entrySet()) {
myLineToOffsetMapping.put(entry.getKey(), entry.getValue() + myStringBuilder.length());
}
}
myStringBuilder.append(buffer.myStringBuilder);
return this;
}
private void checkMapCreated() {
if (myLineToOffsetMapping == null) {
myLineToOffsetMapping = new HashMap<Integer, Integer>();
}
}
public void insert(int offset, String s) {
if (myLineToOffsetMapping != null) {
throw new IllegalStateException("insert not yet supported with Line mapping");
}
myStringBuilder.insert(offset, s);
}
}
@@ -1,11 +1,11 @@
package org.jetbrains.java.decompiler.main.collectors;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.HashMap;
import java.util.Map.Entry;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
public class BytecodeSourceMapper {
private int offset_total;
@@ -37,12 +37,9 @@ public class BytecodeSourceMapper {
}
}
public void dumpMapping(StringBuilder buffer) {
public void dumpMapping(TextBuffer buffer) {
String lineSeparator = DecompilerContext.getNewLineSeparator();
String indentstr1 = InterpreterUtil.getIndentString(1);
String indentstr2 = InterpreterUtil.getIndentString(2);
for(Entry<String, HashMap<String, HashMap<Integer, Integer>>> class_entry : mapping.entrySet()) {
HashMap<String, HashMap<Integer, Integer>> class_mapping = class_entry.getValue();
@@ -54,17 +51,17 @@ public class BytecodeSourceMapper {
HashMap<Integer, Integer> method_mapping = method_entry.getValue();
if(!is_first_method) {
buffer.append(lineSeparator);
buffer.appendLineSeparator();
}
buffer.append(indentstr1 + "method " + method_entry.getKey() + "{" + lineSeparator);
buffer.appendIndent(1).append("method " + method_entry.getKey() + "{" + lineSeparator);
for(Entry<Integer, Integer> line : method_mapping.entrySet()) {
buffer.append(indentstr2 + line.getKey() + indentstr2 + (line.getValue() +offset_total) + lineSeparator);
buffer.appendIndent(2).append(line.getKey().toString()).appendIndent(2).append((line.getValue() + offset_total) + lineSeparator);
}
buffer.append(indentstr1 + "}" + lineSeparator);
buffer.appendIndent(1).append("}").appendLineSeparator();
is_first_method = false;
}
buffer.append("}" + lineSeparator);
buffer.append("}").appendLineSeparator();
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.main.collectors;
import org.jetbrains.java.decompiler.main.ClassesProcessor;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.struct.StructContext;
import java.util.*;
@@ -107,7 +108,7 @@ public class ImportCollector {
return retname == null ? nshort : retname;
}
public int writeImports(StringBuilder buffer) {
public int writeImports(TextBuffer buffer) {
int importlines_written = 0;
String new_line_separator = DecompilerContext.getNewLineSeparator();
@@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.main.decompiler;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.Fernflower;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
@@ -181,12 +182,12 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
}
@Override
public void saveClassFile(String path, String qualifiedName, String entryName, String content) {
public void saveClassFile(String path, String qualifiedName, String entryName, TextBuffer content) {
File file = new File(getAbsolutePath(path), entryName);
try {
Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF8");
try {
out.write(content);
out.write(content.toString());
}
finally {
out.close();
@@ -45,6 +45,7 @@ public interface IFernflowerPreferences {
String LAMBDA_TO_ANONYMOUS_CLASS = "lac";
String BYTECODE_SOURCE_MAPPING = "bsm";
String USE_DEBUG_LINE_NUMBERS = "udl";
String LOG_LEVEL = "log";
String MAX_PROCESSING_METHOD = "mpm";
@@ -80,6 +81,7 @@ public interface IFernflowerPreferences {
put(LAMBDA_TO_ANONYMOUS_CLASS, "0");
put(BYTECODE_SOURCE_MAPPING, "0");
put(USE_DEBUG_LINE_NUMBERS, "0");
put(LOG_LEVEL, IFernflowerLogger.Severity.INFO.name());
put(MAX_PROCESSING_METHOD, "0");
@@ -15,6 +15,8 @@
*/
package org.jetbrains.java.decompiler.main.extern;
import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.jar.Manifest;
public interface IResultSaver {
@@ -22,7 +24,7 @@ public interface IResultSaver {
void copyFile(String source, String path, String entryName);
void saveClassFile(String path, String qualifiedName, String entryName, String content);
void saveClassFile(String path, String qualifiedName, String entryName, TextBuffer content);
void createArchive(String path, String archiveName, Manifest manifest);
@@ -20,6 +20,7 @@ import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
@@ -857,14 +858,14 @@ public class ExprProcessor implements CodeConstants {
return defaultval;
}
public static boolean getCastedExprent(Exprent exprent, VarType leftType, StringBuilder buffer, int indent,
public static boolean getCastedExprent(Exprent exprent, VarType leftType, TextBuffer buffer, int indent,
boolean castNull, BytecodeMappingTracer tracer) {
return getCastedExprent(exprent, leftType, buffer, indent, castNull, false, tracer);
}
public static boolean getCastedExprent(Exprent exprent,
VarType leftType,
StringBuilder buffer,
TextBuffer buffer,
int indent,
boolean castNull,
boolean castAlways, BytecodeMappingTracer tracer) {
@@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@@ -81,7 +82,7 @@ public class ExitExprent extends Exprent {
tracer.addMapping(bytecode);
if (exittype == EXIT_RETURN) {
StringBuilder buffer = new StringBuilder();
TextBuffer buffer = new TextBuffer();
if (rettype.type != CodeConstants.TYPE_VOID) {
buffer.append(" ");
@@ -115,7 +116,7 @@ public class ExitExprent extends Exprent {
if (classname != null) {
VarType exctype = new VarType(classname, true);
StringBuilder buffer = new StringBuilder();
TextBuffer buffer = new TextBuffer();
ExprProcessor.getCastedExprent(value, exctype, buffer, indent, false, tracer);
return "throw " + buffer.toString();
@@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@@ -137,7 +138,7 @@ public class FieldExprent extends Exprent {
buf.append("super");
}
else {
StringBuilder buff = new StringBuilder();
TextBuffer buff = new TextBuffer();
boolean casted = ExprProcessor.getCastedExprent(instance, new VarType(CodeConstants.TYPE_OBJECT, 0, classname), buff, indent, true, tracer);
String res = buff.toString();
@@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
@@ -360,7 +361,7 @@ public class InvocationExprent extends Exprent {
buf.append(", ");
}
StringBuilder buff = new StringBuilder();
TextBuffer buff = new TextBuffer();
ExprProcessor.getCastedExprent(lstParameters.get(i), descriptor.params[i], buff, indent, true, setAmbiguousParameters.contains(i), tracer);
buf.append(buff);
@@ -19,6 +19,7 @@ import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@@ -172,7 +173,7 @@ public class NewExprent extends Exprent {
@Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buf = new StringBuilder();
TextBuffer buf = new TextBuffer();
if (anonymous) {
@@ -220,7 +221,7 @@ public class NewExprent extends Exprent {
}
}
StringBuilder buff = new StringBuilder();
TextBuffer buff = new TextBuffer();
ExprProcessor.getCastedExprent(param, invsuper.getDescriptor().params[i], buff, indent, true, tracer);
buf.append(buff);
@@ -317,7 +318,7 @@ public class NewExprent extends Exprent {
buf.append(", ");
}
StringBuilder buff = new StringBuilder();
TextBuffer buff = new TextBuffer();
ExprProcessor.getCastedExprent(lstParameters.get(i), constructor.getDescriptor().params[i], buff, indent, true, tracer);
buf.append(buff);
@@ -373,7 +374,7 @@ public class NewExprent extends Exprent {
if (i > 0) {
buf.append(", ");
}
StringBuilder buff = new StringBuilder();
TextBuffer buff = new TextBuffer();
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false, tracer);
buf.append(buff);
@@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@@ -83,7 +84,7 @@ public class VarExprent extends Exprent {
@Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buffer = new StringBuilder();
TextBuffer buffer = new TextBuffer();
tracer.addMapping(bytecode);
@@ -15,6 +15,7 @@
*/
package org.jetbrains.java.decompiler.struct;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader.Link;
@@ -110,7 +111,7 @@ public class ContextUnit {
StructClass cl = classes.get(i);
String entryName = decompiledData.getClassEntryName(cl, classEntries.get(i));
if (entryName != null) {
String content = decompiledData.getClassContent(cl);
TextBuffer content = decompiledData.getClassContent(cl);
if (content != null) {
resultSaver.saveClassFile(filename, cl.qualifiedName, entryName, content);
}
@@ -142,8 +143,8 @@ public class ContextUnit {
StructClass cl = classes.get(i);
String entryName = decompiledData.getClassEntryName(cl, classEntries.get(i));
if (entryName != null) {
String content = decompiledData.getClassContent(cl);
resultSaver.saveClassEntry(archivePath, filename, cl.qualifiedName, entryName, content);
TextBuffer content = decompiledData.getClassContent(cl);
resultSaver.saveClassEntry(archivePath, filename, cl.qualifiedName, entryName, content.toString());
}
}
@@ -15,9 +15,11 @@
*/
package org.jetbrains.java.decompiler.struct;
import org.jetbrains.java.decompiler.main.TextBuffer;
public interface IDecompiledData {
String getClassEntryName(StructClass cl, String entryname);
String getClassContent(StructClass cl);
TextBuffer getClassContent(StructClass cl);
}
@@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.util;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import java.io.*;
@@ -92,16 +93,11 @@ public class InterpreterUtil {
public static String getIndentString(int length) {
if (length == 0) return "";
StringBuilder buf = new StringBuilder();
appendIndent(buf, length);
return buf.toString();
}
public static void appendIndent(StringBuilder buffer, int length) {
if (length == 0) return;
String indent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING);
while (length-- > 0) {
buffer.append(indent);
buf.append(indent);
}
return buf.toString();
}
public static boolean equalSets(Collection<?> c1, Collection<?> c2) {
@@ -32,6 +32,7 @@ import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
@@ -47,6 +48,7 @@ import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler;
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
@@ -82,6 +84,7 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
myOptions.put(IFernflowerPreferences.REMOVE_BRIDGE, "1");
myOptions.put(IFernflowerPreferences.LITERALS_AS_IS, "1");
myOptions.put(IFernflowerPreferences.NEW_LINE_SEPARATOR, "1");
//myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, "1");
Project project = DefaultProjectFactory.getInstance().getDefaultProject();
CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings();
@@ -141,13 +144,14 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
MyBytecodeProvider provider = new MyBytecodeProvider(files);
MyResultSaver saver = new MyResultSaver();
myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, Registry.is("decompiler.use.line.table") ? "1" : "0");
BaseDecompiler decompiler = new BaseDecompiler(provider, saver, myOptions, myLogger);
for (String path : files.keySet()) {
decompiler.addSpace(new File(path), true);
}
decompiler.decompileContext();
return BANNER + saver.myResult;
return saver.myResult.addBanner(BANNER).toString();
}
catch (Exception e) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
@@ -183,11 +187,11 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
}
private static class MyResultSaver implements IResultSaver {
private String myResult = "";
private TextBuffer myResult = null;
@Override
public void saveClassFile(String path, String qualifiedName, String entryName, String content) {
if (myResult.isEmpty()) {
public void saveClassFile(String path, String qualifiedName, String entryName, TextBuffer content) {
if (myResult == null || myResult.length() == 0) {
myResult = content;
}
}
@@ -50,10 +50,5 @@
</component>
</project-components>
<module-components>
<component>
<implementation-class>com.intellij.openapi.vcs.impl.VcsManagerPerModuleConfiguration</implementation-class>
</component>
</module-components>
</components>