├── ASM-BO.iml ├── META-INF └── plugin.xml ├── README ├── lib ├── reloc-asm-all-5.0.3.jar └── rules.txt └── src ├── images └── asm.gif └── org └── objectweb └── asm └── idea ├── ACodeView.java ├── BytecodeASMified.java ├── BytecodeOutline.java ├── BytecodeOutlineToolWindowFactory.java ├── Constants.java ├── GroovifiedTextifier.java ├── GroovifiedView.java ├── ShowBytecodeOutlineAction.java └── config ├── ASMPluginComponent.java ├── ASMPluginConfiguration.form ├── ASMPluginConfiguration.java └── GroovyCodeStyle.java /ASM-BO.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 37 | 195 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | ASM Bytecode Outline 3 | Displays bytecode for Java classes and ASMified code which will help you in your class generation. 4 | 0.3.5 5 | Cédric Champeau 6 | 7 | 8 | Version 0.3.5 10 |
    11 |
  • Fixed ASM lib classes version
  • 12 |
  • Upgraded ASM to 5.0.5
  • 13 |
14 | Version 0.3.4 15 |
    16 |
  • Support bytecode display for inner classes based on the caret position in the active editor
  • 17 |
  • Fix outline not beeing always updated when file changed
  • 18 |
19 | Version 0.3.3 20 |
    21 |
  • Upgraded ASM to 5.0
  • 22 |
23 | Version 0.3.2 24 |
    25 |
  • Upgraded ASM to 4.0
  • 26 |
27 | Version 0.3.1 28 |
    29 |
  • Updated for IntelliJ IDEA 10.0.2
  • 30 |
  • Supports showing bytecode for .class files for which we have source code
  • 31 |
32 | Version 0.3 33 |
    34 |
  • Add diff view popup which shows the differences with the previous version of bytecode
  • 35 |
  • Search in every output directory, including test files
  • 36 |
  • Support for Groovy @groovyx.ast.bytecode.Bytecode annotation
  • 37 |
  • Configuration of ASM ClassReader flags
  • 38 |
  • Configuration of Groovy code style
  • 39 |
40 | Version 0.2 41 |
    42 |
  • Fixed .class files not being found under Windows
  • 43 |
  • Fixed tool window not opening if output directory doesn't exist
  • 44 |
  • Added shortcut in "Code" menu
  • 45 |
  • Do not compile file if up-to-date
  • 46 |
47 | ]]>
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.objectweb.asm.idea.config.ASMPluginComponent 56 | 57 | 58 | 59 | 60 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 72 | 74 | 76 | 78 | 79 |
80 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This file was created by IntelliJ IDEA 10.0.1 for binding GitHub repository -------------------------------------------------------------------------------- /lib/reloc-asm-all-5.0.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melix/asm-bytecode-intellij/b348bbe5de2f578d1912a5f982c3ed65eac6758a/lib/reloc-asm-all-5.0.3.jar -------------------------------------------------------------------------------- /lib/rules.txt: -------------------------------------------------------------------------------- 1 | rule org.objectweb.** reloc.org.objectweb.@1 2 | -------------------------------------------------------------------------------- /src/images/asm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melix/asm-bytecode-intellij/b348bbe5de2f578d1912a5f982c3ed65eac6758a/src/images/asm.gif -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/ACodeView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea; 20 | /** 21 | * Created by IntelliJ IDEA. 22 | * User: cedric 23 | * Date: 07/01/11 24 | * Time: 22:18 25 | */ 26 | 27 | import com.intellij.openapi.Disposable; 28 | import com.intellij.openapi.actionSystem.*; 29 | import com.intellij.openapi.diff.DiffContent; 30 | import com.intellij.openapi.diff.DiffManager; 31 | import com.intellij.openapi.diff.DiffRequest; 32 | import com.intellij.openapi.diff.SimpleContent; 33 | import com.intellij.openapi.editor.Document; 34 | import com.intellij.openapi.editor.Editor; 35 | import com.intellij.openapi.editor.EditorFactory; 36 | import com.intellij.openapi.fileTypes.FileTypeManager; 37 | import com.intellij.openapi.keymap.KeymapManager; 38 | import com.intellij.openapi.options.ShowSettingsUtil; 39 | import com.intellij.openapi.project.Project; 40 | import com.intellij.openapi.ui.SimpleToolWindowPanel; 41 | import com.intellij.openapi.util.IconLoader; 42 | import com.intellij.openapi.vfs.VirtualFile; 43 | import com.intellij.openapi.wm.ToolWindowManager; 44 | import com.intellij.psi.PsiFile; 45 | import com.intellij.psi.PsiFileFactory; 46 | import com.intellij.ui.PopupHandler; 47 | import org.objectweb.asm.idea.config.ASMPluginComponent; 48 | 49 | import javax.swing.*; 50 | import java.awt.*; 51 | import java.awt.event.ActionEvent; 52 | import java.awt.event.MouseAdapter; 53 | import java.awt.event.MouseEvent; 54 | 55 | /** 56 | * Base class for editors which displays bytecode or ASMified code. 57 | */ 58 | public class ACodeView extends SimpleToolWindowPanel implements Disposable { 59 | private static final String DIFF_WINDOW_TITLE = "Show differences from previous class contents"; 60 | private static final String[] DIFF_TITLES = {"Previous version", "Current version"}; 61 | protected final Project project; 62 | 63 | protected final ToolWindowManager toolWindowManager; 64 | protected final KeymapManager keymapManager; 65 | private final String extension; 66 | 67 | 68 | protected Editor editor; 69 | protected Document document; 70 | // used for diff view 71 | private String previousCode; 72 | private VirtualFile previousFile; 73 | 74 | public ACodeView(final ToolWindowManager toolWindowManager, KeymapManager keymapManager, final Project project, final String fileExtension) { 75 | super(true, true); 76 | this.toolWindowManager = toolWindowManager; 77 | this.keymapManager = keymapManager; 78 | this.project = project; 79 | this.extension = fileExtension; 80 | setupUI(); 81 | } 82 | 83 | public ACodeView(final ToolWindowManager toolWindowManager, KeymapManager keymapManager, final Project project) { 84 | this(toolWindowManager, keymapManager, project, "java"); 85 | } 86 | 87 | private void setupUI() { 88 | final EditorFactory editorFactory = EditorFactory.getInstance(); 89 | document = editorFactory.createDocument(""); 90 | editor = editorFactory.createEditor(document, project, FileTypeManager.getInstance().getFileTypeByExtension(extension), true); 91 | 92 | final JComponent editorComponent = editor.getComponent(); 93 | add(editorComponent); 94 | final AnAction diffAction = createShowDiffAction(); 95 | DefaultActionGroup group = new DefaultActionGroup(); 96 | group.add(diffAction); 97 | group.add(new ShowSettingsAction()); 98 | 99 | final ActionManager actionManager = ActionManager.getInstance(); 100 | final ActionToolbar actionToolBar = actionManager.createActionToolbar("ASM", group, true); 101 | final JPanel buttonsPanel = new JPanel(new BorderLayout()); 102 | buttonsPanel.add(actionToolBar.getComponent(), BorderLayout.CENTER); 103 | PopupHandler.installPopupHandler(editor.getContentComponent(), group, "ASM", actionManager); 104 | setToolbar(buttonsPanel); 105 | } 106 | 107 | public void setCode(final VirtualFile file, final String code) { 108 | final String text = document.getText(); 109 | if (previousFile == null || file == null || previousFile.getPath().equals(file.getPath()) && !Constants.NO_CLASS_FOUND.equals(text)) { 110 | if (file != null) previousCode = text; 111 | } else if (!previousFile.getPath().equals(file.getPath())) { 112 | previousCode = ""; // reset previous code 113 | } 114 | document.setText(code); 115 | if (file != null) previousFile = file; 116 | } 117 | 118 | 119 | 120 | public void dispose() { 121 | if (editor != null) { 122 | final EditorFactory editorFactory = EditorFactory.getInstance(); 123 | editorFactory.releaseEditor(editor); 124 | editor = null; 125 | } 126 | } 127 | 128 | private AnAction createShowDiffAction() { 129 | return new ShowDiffAction(); 130 | } 131 | 132 | private class ShowSettingsAction extends AnAction { 133 | 134 | private ShowSettingsAction() { 135 | super("Settings", "Show settings for ASM plugin", IconLoader.getIcon("/general/projectSettings.png")); 136 | } 137 | 138 | @Override 139 | public boolean displayTextInToolbar() { 140 | return true; 141 | } 142 | 143 | @Override 144 | public void actionPerformed(final AnActionEvent e) { 145 | ShowSettingsUtil.getInstance().showSettingsDialog(project, project.getComponent(ASMPluginComponent.class)); 146 | } 147 | } 148 | private class ShowDiffAction extends AnAction { 149 | 150 | public ShowDiffAction() { 151 | super("Show differences", 152 | "Shows differences from the previous version of bytecode for this file", 153 | IconLoader.getIcon("/actions/diffWithCurrent.png")); 154 | } 155 | 156 | @Override 157 | public void update(final AnActionEvent e) { 158 | e.getPresentation().setEnabled(!"".equals(previousCode) && (previousFile!=null)); 159 | } 160 | 161 | @Override 162 | public boolean displayTextInToolbar() { 163 | return true; 164 | } 165 | 166 | @Override 167 | public void actionPerformed(final AnActionEvent e) { 168 | DiffManager.getInstance().getDiffTool().show(new DiffRequest(project) { 169 | @Override 170 | public DiffContent[] getContents() { 171 | // there must be a simpler way to obtain the file type 172 | PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("asm." + extension, ""); 173 | final DiffContent currentContent = previousFile == null ? new SimpleContent("") : new SimpleContent(document.getText(), psiFile.getFileType()); 174 | final DiffContent oldContent = new SimpleContent(previousCode == null ? "" : previousCode, psiFile.getFileType()); 175 | return new DiffContent[]{ 176 | oldContent, 177 | currentContent 178 | }; 179 | } 180 | 181 | @Override 182 | public String[] getContentTitles() { 183 | return DIFF_TITLES; 184 | } 185 | 186 | @Override 187 | public String getWindowTitle() { 188 | return DIFF_WINDOW_TITLE; 189 | } 190 | }); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/BytecodeASMified.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea; 20 | 21 | import com.intellij.openapi.components.ServiceManager; 22 | import com.intellij.openapi.keymap.KeymapManager; 23 | import com.intellij.openapi.project.Project; 24 | import com.intellij.openapi.wm.ToolWindowManager; 25 | 26 | import javax.swing.*; 27 | import java.awt.*; 28 | 29 | 30 | /** 31 | * Created by IntelliJ IDEA. 32 | * User: cedric 33 | * Date: 07/01/11 34 | * Time: 17:07 35 | */ 36 | 37 | /** 38 | * ASMified code view. 39 | */ 40 | public class BytecodeASMified extends ACodeView { 41 | 42 | public BytecodeASMified(final ToolWindowManager toolWindowManager, KeymapManager keymapManager, final Project project) { 43 | super(toolWindowManager, keymapManager, project); 44 | } 45 | 46 | public static BytecodeASMified getInstance(Project project) { 47 | return ServiceManager.getService(project, BytecodeASMified.class); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/BytecodeOutline.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea; 20 | 21 | import com.intellij.openapi.components.ProjectComponent; 22 | import com.intellij.openapi.components.ServiceManager; 23 | import com.intellij.openapi.keymap.KeymapManager; 24 | import com.intellij.openapi.project.Project; 25 | import com.intellij.openapi.ui.ComponentContainer; 26 | import com.intellij.openapi.wm.ToolWindow; 27 | import com.intellij.openapi.wm.ToolWindowAnchor; 28 | import com.intellij.openapi.wm.ToolWindowManager; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | import javax.swing.*; 32 | import java.awt.*; 33 | 34 | 35 | /** 36 | * Created by IntelliJ IDEA. 37 | * User: cedric 38 | * Date: 07/01/11 39 | * Time: 17:07 40 | */ 41 | 42 | /** 43 | * Bytecode view. 44 | */ 45 | public class BytecodeOutline extends ACodeView { 46 | 47 | public BytecodeOutline(final Project project, KeymapManager keymapManager, final ToolWindowManager toolWindowManager) { 48 | super(toolWindowManager, keymapManager, project); 49 | } 50 | 51 | public static BytecodeOutline getInstance(Project project) { 52 | return ServiceManager.getService(project, BytecodeOutline.class); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/BytecodeOutlineToolWindowFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea; 20 | 21 | import com.intellij.openapi.project.Project; 22 | import com.intellij.openapi.wm.ToolWindow; 23 | import com.intellij.openapi.wm.ToolWindowFactory; 24 | import com.intellij.openapi.wm.ToolWindowManager; 25 | import com.intellij.ui.content.ContentFactory; 26 | 27 | /** 28 | * ASM ToolWindow factory 29 | */ 30 | public class BytecodeOutlineToolWindowFactory implements ToolWindowFactory{ 31 | public void createToolWindowContent(final Project project, final ToolWindow toolWindow) { 32 | BytecodeOutline outline = BytecodeOutline.getInstance(project); 33 | BytecodeASMified asmified = BytecodeASMified.getInstance(project); 34 | GroovifiedView groovified = GroovifiedView.getInstance(project); 35 | toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(outline, "Bytecode", false)); 36 | toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(asmified, "ASMified", false)); 37 | toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(groovified, "Groovified", false)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | package org.objectweb.asm.idea; 19 | 20 | /** 21 | * Created by IntelliJ IDEA. 22 | * User: cedric 23 | * Date: 18/01/11 24 | * Time: 06:58 25 | */ 26 | 27 | /** 28 | * Constants used in various places of the code. 29 | */ 30 | public abstract class Constants { 31 | final static String NO_CLASS_FOUND = "// couldn't generate bytecode view, no .class file found"; 32 | } 33 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/GroovifiedTextifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea; 20 | /** 21 | * Created by IntelliJ IDEA. 22 | * User: cedric 23 | * Date: 17/01/11 24 | * Time: 22:07 25 | */ 26 | 27 | import org.objectweb.asm.*; 28 | import reloc.org.objectweb.asm.*; 29 | import reloc.org.objectweb.asm.Label; 30 | import reloc.org.objectweb.asm.Opcodes; 31 | import reloc.org.objectweb.asm.Type; 32 | import reloc.org.objectweb.asm.commons.Method; 33 | import org.objectweb.asm.idea.config.GroovyCodeStyle; 34 | import reloc.org.objectweb.asm.util.*; 35 | 36 | import java.util.Collections; 37 | import java.util.HashMap; 38 | import java.util.List; 39 | 40 | /** 41 | * A customized trace visitor which outputs code compatible with the Groovy @groovyx.ast.bytecode.Bytecode AST 42 | * transform. 43 | */ 44 | public class GroovifiedTextifier extends Textifier { 45 | 46 | private final static String[] GROOVY_DEFAULT_IMPORTS = { 47 | "java.io.", 48 | "java.lang.", 49 | "java.net.", 50 | "java.util.", 51 | "groovy.lang.", 52 | "groovy.util." 53 | }; 54 | 55 | private final static String[] ATYPES; 56 | 57 | static { 58 | ATYPES = new String[12]; 59 | String s = "boolean,char,float,double,byte,short,int,long,"; 60 | int j = 0; 61 | int i = 4; 62 | int l; 63 | while ((l = s.indexOf(',', j)) > 0) { 64 | ATYPES[i++] = s.substring(j, l); 65 | j = l + 1; 66 | } 67 | } 68 | 69 | private final GroovyCodeStyle codeStyle; 70 | 71 | public GroovifiedTextifier(final GroovyCodeStyle codeStyle) { 72 | super( Opcodes.ASM5 ); 73 | this.codeStyle = codeStyle; 74 | } 75 | 76 | protected Textifier createTextifier() { 77 | return new GroovifiedMethodTextifier(codeStyle); 78 | } 79 | 80 | @Override 81 | public Textifier visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { 82 | buf.setLength(0); 83 | buf.append('\n'); 84 | if ((access & Opcodes.ACC_DEPRECATED) != 0) { 85 | buf.append(tab).append("// @Deprecated\n"); 86 | } 87 | buf.append(tab).append("@groovyx.ast.bytecode.Bytecode\n"); 88 | Method method = new Method(name, desc); 89 | 90 | buf.append(tab); 91 | appendAccess(access); 92 | if ((access & Opcodes.ACC_NATIVE) != 0) { 93 | buf.append("native "); 94 | } 95 | buf.append(groovyClassName(method.getReturnType().getClassName())); 96 | buf.append(' '); 97 | buf.append(name); 98 | buf.append('('); 99 | final Type[] argumentTypes = method.getArgumentTypes(); 100 | char arg = 'a'; 101 | for (int j = 0, argumentTypesLength = argumentTypes.length; j < argumentTypesLength; j++) { 102 | final Type type = argumentTypes[j]; 103 | buf.append(groovyClassName(type.getClassName())); 104 | buf.append(' '); 105 | buf.append(arg); 106 | if (j < argumentTypesLength - 1) buf.append(','); 107 | arg++; 108 | } 109 | buf.append(')'); 110 | if (exceptions != null && exceptions.length > 0) { 111 | buf.append(" throws "); 112 | for (int i = 0; i < exceptions.length; ++i) { 113 | appendDescriptor(INTERNAL_NAME, exceptions[i].replace('/', '.')); 114 | if (i < exceptions.length - 1) buf.append(','); 115 | } 116 | } 117 | buf.append(" {"); 118 | buf.append('\n'); 119 | text.add(buf.toString()); 120 | 121 | GroovifiedMethodTextifier tcv = (GroovifiedMethodTextifier) createTextifier(); 122 | text.add(tcv.getText()); 123 | text.add(" }\n"); 124 | return tcv; 125 | } 126 | 127 | /** 128 | * Appends a string representation of the given access modifiers to {@link #buf buf}. 129 | * 130 | * @param access some access modifiers. 131 | */ 132 | private void appendAccess(final int access) { 133 | if ((access & Opcodes.ACC_PUBLIC) != 0) { 134 | buf.append("public "); 135 | } 136 | if ((access & Opcodes.ACC_PRIVATE) != 0) { 137 | buf.append("private "); 138 | } 139 | if ((access & Opcodes.ACC_PROTECTED) != 0) { 140 | buf.append("protected "); 141 | } 142 | if ((access & Opcodes.ACC_FINAL) != 0) { 143 | buf.append("final "); 144 | } 145 | if ((access & Opcodes.ACC_STATIC) != 0) { 146 | buf.append("static "); 147 | } 148 | if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { 149 | buf.append("synchronized "); 150 | } 151 | if ((access & Opcodes.ACC_VOLATILE) != 0) { 152 | buf.append("volatile "); 153 | } 154 | if ((access & Opcodes.ACC_TRANSIENT) != 0) { 155 | buf.append("transient "); 156 | } 157 | if ((access & Opcodes.ACC_ABSTRACT) != 0) { 158 | buf.append("abstract "); 159 | } 160 | if ((access & Opcodes.ACC_STRICT) != 0) { 161 | buf.append("strictfp "); 162 | } 163 | if ((access & Opcodes.ACC_ENUM) != 0) { 164 | buf.append("enum "); 165 | } 166 | } 167 | 168 | private static String groovyClassName(String className) { 169 | for (String anImport : GROOVY_DEFAULT_IMPORTS) { 170 | if (className.startsWith(anImport)) return className.substring(anImport.length()); 171 | } 172 | return className; 173 | } 174 | 175 | protected static class GroovifiedMethodTextifier extends Textifier { 176 | 177 | private final GroovyCodeStyle codeStyle; 178 | private static final Textifier EMPTY_TEXTIFIER = new Textifier( Opcodes.ASM5 ) { 179 | @Override 180 | public List getText() { 181 | return Collections.emptyList(); 182 | } 183 | }; 184 | 185 | public GroovifiedMethodTextifier(final GroovyCodeStyle codeStyle) { 186 | super( Opcodes.ASM5 ); 187 | this.codeStyle = codeStyle; 188 | } 189 | 190 | private boolean isLegacy() { 191 | return codeStyle == GroovyCodeStyle.LEGACY; 192 | } 193 | 194 | @Override 195 | public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) { 196 | // frames are not supported 197 | } 198 | 199 | @Override 200 | public void visitLineNumber(final int line, final Label start) { 201 | // line numbers are not necessary 202 | } 203 | 204 | public void visitInsn(final int opcode) { 205 | buf.setLength(0); 206 | buf.append(tab2).append(OPCODES[opcode].toLowerCase()).append('\n'); 207 | text.add(buf.toString()); 208 | } 209 | 210 | public void visitIntInsn(final int opcode, final int operand) { 211 | buf.setLength(0); 212 | buf.append(tab2) 213 | .append(OPCODES[opcode].toLowerCase()) 214 | .append(' ') 215 | .append(opcode == Opcodes.NEWARRAY 216 | ? (isLegacy() ? TYPES[operand] : ATYPES[operand]) 217 | : Integer.toString(operand)) 218 | .append('\n'); 219 | text.add(buf.toString()); 220 | } 221 | 222 | public void visitVarInsn(final int opcode, final int var) { 223 | buf.setLength(0); 224 | buf.append(tab2) 225 | .append(OPCODES[opcode].toLowerCase()) 226 | .append(' ') 227 | .append(var) 228 | .append('\n'); 229 | text.add(buf.toString()); 230 | } 231 | 232 | public void visitTypeInsn(final int opcode, final String type) { 233 | buf.setLength(0); 234 | final String opcodeStr = OPCODES[opcode]; 235 | buf.append(tab2).append("NEW".equals(opcodeStr) ? 236 | (isLegacy() ? "_new" : "newobject") 237 | : "INSTANCEOF".equals(opcodeStr) ? 238 | (isLegacy() ? "_instanceof" : "instance of:") : opcodeStr.toLowerCase()).append(' '); 239 | if (isLegacy()) { 240 | buf.append('\''); 241 | appendDescriptor(INTERNAL_NAME, type); 242 | buf.append('\''); 243 | } else { 244 | buf.append(groovyClassName(type.replace('/', '.'))); 245 | } 246 | buf.append('\n'); 247 | text.add(buf.toString()); 248 | } 249 | 250 | public void visitFieldInsn( 251 | final int opcode, 252 | final String owner, 253 | final String name, 254 | final String desc) { 255 | buf.setLength(0); 256 | buf.append(tab2).append(OPCODES[opcode].toLowerCase()).append(' '); 257 | if (isLegacy()) { 258 | buf.append('\''); 259 | appendDescriptor(INTERNAL_NAME, owner); 260 | buf.append('.').append(name).append("','"); 261 | appendDescriptor(FIELD_DESCRIPTOR, desc); 262 | buf.append('\''); 263 | } else { 264 | buf.append(groovyClassName(Type.getObjectType(owner).getClassName())); 265 | buf.append('.'); 266 | buf.append(name); 267 | buf.append(" >> "); 268 | buf.append(groovyClassName(Type.getReturnType(desc).getClassName())); 269 | } 270 | buf.append('\n'); 271 | text.add(buf.toString()); 272 | 273 | } 274 | 275 | public void visitMethodInsn( 276 | final int opcode, 277 | final String owner, 278 | final String name, 279 | final String desc) { 280 | buf.setLength(0); 281 | buf.append(tab2).append(OPCODES[opcode].toLowerCase()).append(' '); 282 | if (isLegacy()) { 283 | buf.append('\''); 284 | appendDescriptor(INTERNAL_NAME, owner); 285 | buf.append('.').append(name).append("','"); 286 | appendDescriptor(METHOD_DESCRIPTOR, desc); 287 | buf.append('\''); 288 | } else { 289 | buf.append(groovyClassName(Type.getObjectType(owner).getClassName())); 290 | buf.append('.'); 291 | if ("".equals(name)) buf.append('"'); 292 | buf.append(name); 293 | if ("".equals(name)) buf.append('"'); 294 | buf.append('('); 295 | final Type[] types = Type.getArgumentTypes(desc); 296 | for (int i = 0; i < types.length; i++) { 297 | Type type = types[i]; 298 | buf.append(groovyClassName(type.getClassName())); 299 | if (i < types.length - 1) buf.append(','); 300 | } 301 | buf.append(") >> "); 302 | buf.append(groovyClassName(Type.getReturnType(desc).getClassName())); 303 | } 304 | buf.append('\n'); 305 | text.add(buf.toString()); 306 | } 307 | 308 | public void visitJumpInsn(final int opcode, final Label label) { 309 | buf.setLength(0); 310 | buf.append(tab2).append( 311 | OPCODES[opcode].equals("GOTO") ? 312 | (isLegacy() ? "_goto" : "go to:") 313 | : OPCODES[opcode].toLowerCase()).append(' '); 314 | appendLabel(label); 315 | buf.append('\n'); 316 | text.add(buf.toString()); 317 | } 318 | 319 | @Override 320 | public Textifier visitParameterAnnotation(final int parameter, final String desc, final boolean visible) { 321 | return EMPTY_TEXTIFIER; 322 | } 323 | 324 | @Override 325 | public Textifier visitAnnotation(final String desc, final boolean visible) { 326 | return EMPTY_TEXTIFIER; 327 | } 328 | 329 | @Override 330 | public Textifier visitAnnotationDefault() { 331 | return EMPTY_TEXTIFIER; 332 | } 333 | 334 | /** 335 | * Appends the name of the given label to {@link #buf buf}. Creates a new label name if the given label does not 336 | * yet have one. 337 | * 338 | * @param l a label. 339 | */ 340 | protected void appendLabel(final Label l) { 341 | if (labelNames == null) { 342 | labelNames = new HashMap(); 343 | } 344 | String name = (String) labelNames.get(l); 345 | if (name == null) { 346 | name = "l" + labelNames.size(); 347 | labelNames.put(l, name); 348 | } 349 | buf.append(name); 350 | } 351 | 352 | public void visitLabel(final Label label) { 353 | buf.setLength(0); 354 | buf.append(ltab); 355 | appendLabel(label); 356 | if (codeStyle == GroovyCodeStyle.GROOVIFIER_0_2_0) buf.append(':'); 357 | buf.append('\n'); 358 | text.add(buf.toString()); 359 | } 360 | 361 | public void visitLdcInsn(final Object cst) { 362 | buf.setLength(0); 363 | buf.append(tab2).append("ldc "); 364 | if (cst instanceof String) { 365 | Printer.appendString(buf, (String) cst); 366 | } else if (cst instanceof Type) { 367 | buf.append(((Type) cst).getDescriptor()).append(".class"); 368 | } else if (cst instanceof Float) { 369 | buf.append(cst).append('f'); 370 | } else if (cst instanceof Double) { 371 | buf.append(cst).append('d'); 372 | } else if (cst instanceof Integer) { 373 | buf.append(cst).append('i'); 374 | } else { 375 | buf.append(cst); 376 | } 377 | buf.append('\n'); 378 | text.add(buf.toString()); 379 | 380 | } 381 | 382 | public void visitIincInsn(final int var, final int increment) { 383 | buf.setLength(0); 384 | buf.append(tab2) 385 | .append("iinc ") 386 | .append(var) 387 | .append(',') 388 | .append(increment) 389 | .append('\n'); 390 | text.add(buf.toString()); 391 | } 392 | 393 | public void visitTableSwitchInsn( 394 | final int min, 395 | final int max, 396 | final Label dflt, 397 | final Label[] labels) { 398 | buf.setLength(0); 399 | buf.append(tab2).append("tableswitch(\n"); 400 | for (int i = 0; i < labels.length; ++i) { 401 | buf.append(tab3).append(min + i).append(": "); 402 | appendLabel(labels[i]); 403 | buf.append(",\n"); 404 | } 405 | buf.append(tab3).append("default: "); 406 | appendLabel(dflt); 407 | buf.append(tab2).append("\n)\n"); 408 | text.add(buf.toString()); 409 | } 410 | 411 | public void visitLookupSwitchInsn( 412 | final Label dflt, 413 | final int[] keys, 414 | final Label[] labels) { 415 | buf.setLength(0); 416 | buf.append(tab2).append("lookupswitch(\n"); 417 | for (int i = 0; i < labels.length; ++i) { 418 | buf.append(tab3).append(keys[i]).append(": "); 419 | appendLabel(labels[i]); 420 | buf.append(",\n"); 421 | } 422 | buf.append(tab3).append("default: "); 423 | appendLabel(dflt); 424 | buf.append(tab2).append("\n)\n"); 425 | text.add(buf.toString()); 426 | } 427 | 428 | public void visitMultiANewArrayInsn(final String desc, final int dims) { 429 | buf.setLength(0); 430 | buf.append(tab2).append("multianewarray "); 431 | if (isLegacy()) { 432 | buf.append('\''); 433 | appendDescriptor(FIELD_DESCRIPTOR, desc); 434 | buf.append("\'"); 435 | } else { 436 | buf.append(groovyClassName(Type.getType(desc).getClassName())); 437 | } 438 | buf.append(',').append(dims).append('\n'); 439 | text.add(buf.toString()); 440 | } 441 | 442 | public void visitTryCatchBlock( 443 | final Label start, 444 | final Label end, 445 | final Label handler, 446 | final String type) { 447 | buf.setLength(0); 448 | buf.append(tab2).append("trycatchblock "); 449 | appendLabel(start); 450 | buf.append(','); 451 | appendLabel(end); 452 | buf.append(','); 453 | appendLabel(handler); 454 | buf.append(','); 455 | if (type != null) { 456 | if (isLegacy()) { 457 | buf.append('\''); 458 | appendDescriptor(INTERNAL_NAME, type); 459 | buf.append('\''); 460 | } else { 461 | buf.append(groovyClassName(type.replace('/', '.'))); 462 | } 463 | } else { 464 | appendDescriptor(INTERNAL_NAME, type); 465 | } 466 | buf.append('\n'); 467 | text.add(buf.toString()); 468 | 469 | } 470 | 471 | @Override 472 | public void visitLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int index) { 473 | } 474 | 475 | @Override 476 | public void visitMaxs(final int maxStack, final int maxLocals) { 477 | } 478 | 479 | } 480 | 481 | 482 | } 483 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/GroovifiedView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea; 20 | 21 | import com.intellij.openapi.components.ServiceManager; 22 | import com.intellij.openapi.keymap.KeymapManager; 23 | import com.intellij.openapi.project.Project; 24 | import com.intellij.openapi.wm.ToolWindowManager; 25 | 26 | 27 | /** 28 | * Created by IntelliJ IDEA. 29 | * User: cedric 30 | * Date: 07/01/11 31 | * Time: 17:07 32 | */ 33 | 34 | /** 35 | * The groovified view displays @groovyx.ast.bytecode.Bytecode code for methods. 36 | */ 37 | public class GroovifiedView extends ACodeView { 38 | 39 | public GroovifiedView(final Project project, KeymapManager keymapManager, final ToolWindowManager toolWindowManager) { 40 | super(toolWindowManager, keymapManager, project, "groovy"); 41 | } 42 | 43 | public static GroovifiedView getInstance(Project project) { 44 | return ServiceManager.getService(project, GroovifiedView.class); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/ShowBytecodeOutlineAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea; 20 | 21 | import com.intellij.openapi.actionSystem.AnAction; 22 | import com.intellij.openapi.actionSystem.AnActionEvent; 23 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 24 | import com.intellij.openapi.actionSystem.Presentation; 25 | import com.intellij.openapi.application.Application; 26 | import com.intellij.openapi.application.ApplicationManager; 27 | import com.intellij.openapi.compiler.CompileContext; 28 | import com.intellij.openapi.compiler.CompileScope; 29 | import com.intellij.openapi.compiler.CompileStatusNotification; 30 | import com.intellij.openapi.compiler.CompilerManager; 31 | import com.intellij.openapi.fileEditor.FileDocumentManager; 32 | import com.intellij.openapi.fileEditor.FileEditor; 33 | import com.intellij.openapi.fileEditor.FileEditorManager; 34 | import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl; 35 | import com.intellij.openapi.module.Module; 36 | import com.intellij.openapi.module.ModuleUtil; 37 | import com.intellij.openapi.project.Project; 38 | import com.intellij.openapi.roots.CompilerModuleExtension; 39 | import com.intellij.openapi.util.Computable; 40 | import com.intellij.openapi.vfs.VirtualFile; 41 | import com.intellij.openapi.wm.ToolWindowManager; 42 | import com.intellij.psi.*; 43 | import com.intellij.psi.codeStyle.CodeStyleManager; 44 | import org.objectweb.asm.idea.config.ASMPluginComponent; 45 | import reloc.org.objectweb.asm.ClassReader; 46 | import reloc.org.objectweb.asm.ClassVisitor; 47 | import reloc.org.objectweb.asm.util.ASMifier; 48 | import reloc.org.objectweb.asm.util.TraceClassVisitor; 49 | 50 | import java.io.IOException; 51 | import java.io.PrintWriter; 52 | import java.io.StringWriter; 53 | import java.util.concurrent.Semaphore; 54 | 55 | 56 | /** 57 | * Given a java file (or any file which generates classes), tries to locate a .class file. If the compilation state is 58 | * not up to date, performs an automatic compilation of the class. If the .class file can be located, generates bytecode 59 | * instructions for the class and ASMified code, and displays them into a tool window. 60 | * 61 | * @author Cédric Champeau 62 | */ 63 | public class ShowBytecodeOutlineAction extends AnAction { 64 | 65 | @Override 66 | public void update(final AnActionEvent e) { 67 | final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); 68 | final Project project = e.getData(PlatformDataKeys.PROJECT); 69 | final Presentation presentation = e.getPresentation(); 70 | if (project == null || virtualFile == null) { 71 | presentation.setEnabled(false); 72 | return; 73 | } 74 | final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); 75 | presentation.setEnabled(psiFile instanceof PsiClassOwner); 76 | } 77 | 78 | public void actionPerformed(AnActionEvent e) { 79 | final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); 80 | final Project project = e.getData(PlatformDataKeys.PROJECT); 81 | if (project == null || virtualFile == null) return; 82 | final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); 83 | if (psiFile instanceof PsiClassOwner) { 84 | final Module module = ModuleUtil.findModuleForPsiElement(psiFile); 85 | final CompilerModuleExtension cme = CompilerModuleExtension.getInstance(module); 86 | final CompilerManager compilerManager = CompilerManager.getInstance(project); 87 | final VirtualFile[] files = {virtualFile}; 88 | if ("class".equals(virtualFile.getExtension())) { 89 | updateToolWindowContents(project, virtualFile); 90 | } else if (!virtualFile.isInLocalFileSystem() && !virtualFile.isWritable()) { 91 | // probably a source file in a library 92 | final PsiClass[] psiClasses = ((PsiClassOwner) psiFile).getClasses(); 93 | if (psiClasses.length>0) { 94 | updateToolWindowContents(project, psiClasses[0].getOriginalElement().getContainingFile().getVirtualFile()); 95 | } 96 | } else { 97 | final Application application = ApplicationManager.getApplication(); 98 | application.runWriteAction(new Runnable() { 99 | public void run() { 100 | FileDocumentManager.getInstance().saveAllDocuments(); 101 | } 102 | }); 103 | application.executeOnPooledThread(new Runnable() { 104 | public void run() { 105 | final CompileScope compileScope = compilerManager.createFilesCompileScope(files); 106 | final VirtualFile[] result = {null}; 107 | final VirtualFile[] outputDirectories = cme == null ? null : cme.getOutputRoots(true); 108 | final Semaphore semaphore = new Semaphore(1); 109 | try { 110 | semaphore.acquire(); 111 | } catch (InterruptedException e1) { 112 | result[0] = null; 113 | } 114 | if (outputDirectories != null && compilerManager.isUpToDate(compileScope)) { 115 | application.invokeLater( new Runnable() { 116 | public void run() { 117 | result[0] = findClassFile( outputDirectories, psiFile ); 118 | semaphore.release(); 119 | } 120 | } ); 121 | } else { 122 | application.invokeLater(new Runnable() { 123 | public void run() { 124 | compilerManager.compile(files, new CompileStatusNotification() { 125 | public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) { 126 | if (errors == 0) { 127 | VirtualFile[] outputDirectories = cme.getOutputRoots(true); 128 | if (outputDirectories != null) { 129 | result[0] = findClassFile(outputDirectories, psiFile); 130 | } 131 | } 132 | semaphore.release(); 133 | } 134 | }); 135 | } 136 | }); 137 | try { 138 | semaphore.acquire(); 139 | } catch (InterruptedException e1) { 140 | result[0] = null; 141 | } 142 | } 143 | application.invokeLater(new Runnable() { 144 | public void run() { 145 | updateToolWindowContents(project, result[0]); 146 | } 147 | }); 148 | } 149 | }); 150 | } 151 | } 152 | } 153 | 154 | private VirtualFile findClassFile(final VirtualFile[] outputDirectories, final PsiFile psiFile) { 155 | return ApplicationManager.getApplication().runReadAction(new Computable() { 156 | public VirtualFile compute() { 157 | if( outputDirectories != null && psiFile instanceof PsiClassOwner ) { 158 | FileEditor editor = FileEditorManager.getInstance( psiFile.getProject() ).getSelectedEditor( psiFile.getVirtualFile() ); 159 | int caretOffset = editor == null ? -1 : ((PsiAwareTextEditorImpl)editor).getEditor().getCaretModel().getOffset(); 160 | if( caretOffset >= 0 ) { 161 | PsiClass psiClass = findClassAtCaret( psiFile, caretOffset ); 162 | if( psiClass != null ) { 163 | return getClassFile( psiClass ); 164 | } 165 | } 166 | PsiClassOwner psiJavaFile = (PsiClassOwner)psiFile; 167 | for( PsiClass psiClass : psiJavaFile.getClasses() ) { 168 | final VirtualFile file = getClassFile( psiClass ); 169 | if( file != null ) { 170 | return file; 171 | } 172 | } 173 | } 174 | return null; 175 | } 176 | 177 | private VirtualFile getClassFile( PsiClass psiClass ) { 178 | StringBuilder sb = new StringBuilder( psiClass.getQualifiedName() ); 179 | while( psiClass.getContainingClass() != null ) { 180 | sb.setCharAt( sb.lastIndexOf( "." ), '$' ); 181 | psiClass = psiClass.getContainingClass(); 182 | } 183 | String classFileName = sb.toString().replace( '.', '/' ) + ".class"; 184 | for( VirtualFile outputDirectory : outputDirectories ) { 185 | final VirtualFile file = outputDirectory.findFileByRelativePath( classFileName ); 186 | if( file != null && file.exists() ) { 187 | return file; 188 | } 189 | } 190 | return null; 191 | } 192 | 193 | private PsiClass findClassAtCaret( PsiFile psiFile, int caretOffset ) { 194 | PsiElement elem = psiFile.findElementAt( caretOffset ); 195 | while( elem != null ) { 196 | if( elem instanceof PsiClass ) { 197 | return (PsiClass)elem; 198 | } 199 | elem = elem.getParent(); 200 | } 201 | return null; 202 | } 203 | }); 204 | } 205 | 206 | /** 207 | * Reads the .class file, processes it through the ASM TraceVisitor and ASMifier to update the contents of the two 208 | * tabs of the tool window. 209 | * 210 | * @param project the project instance 211 | * @param file the class file 212 | */ 213 | private void updateToolWindowContents(final Project project, final VirtualFile file) { 214 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 215 | public void run() { 216 | if (file==null) { 217 | BytecodeOutline.getInstance(project).setCode(file, Constants.NO_CLASS_FOUND); 218 | BytecodeASMified.getInstance(project).setCode(file, Constants.NO_CLASS_FOUND); 219 | GroovifiedView.getInstance(project).setCode(file, Constants.NO_CLASS_FOUND); 220 | ToolWindowManager.getInstance(project).getToolWindow("ASM").activate(null); 221 | return; 222 | } 223 | StringWriter stringWriter = new StringWriter(); 224 | ClassVisitor visitor = new TraceClassVisitor(new PrintWriter(stringWriter)); 225 | ClassReader reader = null; 226 | try { 227 | file.refresh(false, false); 228 | reader = new ClassReader(file.contentsToByteArray()); 229 | } catch (IOException e) { 230 | return; 231 | } 232 | int flags = 0; 233 | final ASMPluginComponent config = project.getComponent(ASMPluginComponent.class); 234 | if (config.isSkipDebug()) flags = flags | ClassReader.SKIP_DEBUG; 235 | if (config.isSkipFrames()) flags = flags | ClassReader.SKIP_FRAMES; 236 | if (config.isExpandFrames()) flags = flags | ClassReader.EXPAND_FRAMES; 237 | if (config.isSkipCode()) flags = flags | ClassReader.SKIP_CODE; 238 | 239 | reader.accept(visitor, flags); 240 | BytecodeOutline.getInstance(project).setCode(file, stringWriter.toString()); 241 | stringWriter.getBuffer().setLength(0); 242 | reader.accept(new TraceClassVisitor(null, new GroovifiedTextifier(config.getCodeStyle()), new PrintWriter(stringWriter)), ClassReader.SKIP_FRAMES|ClassReader.SKIP_DEBUG); 243 | GroovifiedView.getInstance(project).setCode(file,stringWriter.toString()); 244 | stringWriter.getBuffer().setLength(0); 245 | reader.accept(new TraceClassVisitor(null, 246 | new ASMifier(), 247 | new PrintWriter(stringWriter)), flags); 248 | final BytecodeASMified asmified = BytecodeASMified.getInstance(project); 249 | PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("asm.java", stringWriter.toString()); 250 | CodeStyleManager.getInstance(project).reformat(psiFile); 251 | asmified.setCode(file,psiFile.getText()); 252 | ToolWindowManager.getInstance(project).getToolWindow("ASM").activate(null); 253 | } 254 | }); 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/config/ASMPluginComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea.config; 20 | /** 21 | * Created by IntelliJ IDEA. 22 | * User: cedric 23 | * Date: 18/01/11 24 | * Time: 19:51 25 | */ 26 | 27 | import com.intellij.openapi.components.PersistentStateComponent; 28 | import com.intellij.openapi.components.ProjectComponent; 29 | import com.intellij.openapi.components.State; 30 | import com.intellij.openapi.components.Storage; 31 | import com.intellij.openapi.options.Configurable; 32 | import com.intellij.openapi.options.ConfigurationException; 33 | import com.intellij.openapi.project.Project; 34 | import com.intellij.openapi.util.IconLoader; 35 | import org.jdom.Element; 36 | import org.jetbrains.annotations.Nls; 37 | import org.jetbrains.annotations.NotNull; 38 | 39 | import javax.swing.*; 40 | 41 | /** 42 | * A component created just to be able to configure the plugin. 43 | */ 44 | @State( 45 | name = ASMPluginConfiguration.COMPONENT_NAME, 46 | storages = { 47 | @Storage(id = "other", file = "$PROJECT_FILE$") 48 | } 49 | ) 50 | public class ASMPluginComponent implements ProjectComponent, Configurable, PersistentStateComponent { 51 | 52 | private Project project; 53 | private boolean skipFrames = false; 54 | private boolean skipDebug = false; 55 | private boolean skipCode = false; 56 | private boolean expandFrames = false; 57 | private GroovyCodeStyle codeStyle = GroovyCodeStyle.LEGACY; 58 | 59 | private ASMPluginConfiguration configDialog; 60 | 61 | public ASMPluginComponent(final Project project) { 62 | this.project = project; 63 | } 64 | 65 | public void projectOpened() { 66 | } 67 | 68 | public void projectClosed() { 69 | } 70 | 71 | @NotNull 72 | public String getComponentName() { 73 | return "ASM Plugin"; 74 | } 75 | 76 | public void initComponent() { 77 | } 78 | 79 | public void disposeComponent() { 80 | } 81 | 82 | public boolean isSkipCode() { 83 | return skipCode; 84 | } 85 | 86 | public void setSkipCode(final boolean skipCode) { 87 | this.skipCode = skipCode; 88 | } 89 | 90 | public boolean isSkipDebug() { 91 | return skipDebug; 92 | } 93 | 94 | public void setSkipDebug(final boolean skipDebug) { 95 | this.skipDebug = skipDebug; 96 | } 97 | 98 | public boolean isSkipFrames() { 99 | return skipFrames; 100 | } 101 | 102 | public void setSkipFrames(final boolean skipFrames) { 103 | this.skipFrames = skipFrames; 104 | } 105 | 106 | public GroovyCodeStyle getCodeStyle() { 107 | return codeStyle; 108 | } 109 | 110 | public void setCodeStyle(final GroovyCodeStyle codeStyle) { 111 | this.codeStyle = codeStyle; 112 | } 113 | 114 | // -------------- Configurable interface implementation -------------------------- 115 | 116 | @Nls 117 | public String getDisplayName() { 118 | return "ASM Bytecode plugin"; 119 | } 120 | 121 | public Icon getIcon() { 122 | return IconLoader.getIcon("/images/asm.gif"); 123 | } 124 | 125 | public String getHelpTopic() { 126 | return null; 127 | } 128 | 129 | public JComponent createComponent() { 130 | if (configDialog==null) configDialog = new ASMPluginConfiguration(); 131 | return configDialog.getRootPane(); 132 | } 133 | 134 | public boolean isModified() { 135 | return configDialog!=null && configDialog.isModified(this); 136 | } 137 | 138 | public void apply() throws ConfigurationException { 139 | if (configDialog!=null) { 140 | configDialog.getData(this); 141 | } 142 | } 143 | 144 | public void reset() { 145 | if (configDialog!=null) { 146 | configDialog.setData(this); 147 | } 148 | } 149 | 150 | public void disposeUIResources() { 151 | configDialog = null; 152 | } 153 | 154 | public boolean isExpandFrames() { 155 | return expandFrames; 156 | } 157 | 158 | public void setExpandFrames(final boolean expandFrames) { 159 | this.expandFrames = expandFrames; 160 | } 161 | 162 | // -------------------- state persistence 163 | 164 | public Element getState() { 165 | Element root = new Element("state"); 166 | Element asmNode = new Element("asm"); 167 | asmNode.setAttribute("skipDebug", String.valueOf(skipDebug)); 168 | asmNode.setAttribute("skipFrames", String.valueOf(skipFrames)); 169 | asmNode.setAttribute("skipCode", String.valueOf(skipCode)); 170 | asmNode.setAttribute("expandFrames", String.valueOf(expandFrames)); 171 | root.addContent(asmNode); 172 | Element groovyNode = new Element("groovy"); 173 | groovyNode.setAttribute("codeStyle", codeStyle.toString()); 174 | root.addContent(groovyNode); 175 | return root; 176 | } 177 | 178 | public void loadState(final Element state) { 179 | Element asmNode = state.getChild("asm"); 180 | if (asmNode!=null) { 181 | final String skipDebugStr = asmNode.getAttributeValue("skipDebug"); 182 | if (skipDebugStr!=null) skipDebug= Boolean.valueOf(skipDebugStr); 183 | final String skipFramesStr = asmNode.getAttributeValue("skipFrames"); 184 | if (skipFramesStr!=null) skipFrames= Boolean.valueOf(skipFramesStr); 185 | final String skipCodeStr = asmNode.getAttributeValue("skipCode"); 186 | if (skipCodeStr!=null) skipCode = Boolean.valueOf(skipCodeStr); 187 | final String expandFramesStr = asmNode.getAttributeValue("expandFrames"); 188 | if (expandFramesStr!=null) expandFrames = Boolean.valueOf(expandFramesStr); 189 | } 190 | Element groovyNode = state.getChild("groovy"); 191 | if (groovyNode!=null) { 192 | String codeStyleStr = groovyNode.getAttributeValue("codeStyle"); 193 | if (codeStyleStr!=null) codeStyle = GroovyCodeStyle.valueOf(codeStyleStr); 194 | } 195 | } 196 | 197 | } 198 | 199 | 200 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/config/ASMPluginConfiguration.form: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
85 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/config/ASMPluginConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea.config; 20 | 21 | import com.intellij.openapi.components.State; 22 | import com.intellij.openapi.components.Storage; 23 | import com.intellij.openapi.ui.ComboBox; 24 | import com.intellij.ui.EnumComboBoxModel; 25 | 26 | import javax.swing.*; 27 | import java.awt.*; 28 | import java.util.EnumMap; 29 | 30 | public class ASMPluginConfiguration { 31 | protected static final String COMPONENT_NAME = "ASMPluginConfiguration"; 32 | private JPanel contentPane; 33 | private JCheckBox skipDebugCheckBox; 34 | private JCheckBox skipFramesCheckBox; 35 | private JCheckBox skipCodeCheckBox; 36 | private JCheckBox expandFramesCheckBox; 37 | private JComboBox groovyCodeStyleComboBox; 38 | 39 | public ASMPluginConfiguration() { 40 | } 41 | 42 | public JComponent getRootPane() { 43 | return contentPane; 44 | } 45 | 46 | public void setData(ASMPluginComponent data) { 47 | skipDebugCheckBox.setSelected(data.isSkipDebug()); 48 | skipFramesCheckBox.setSelected(data.isSkipFrames()); 49 | skipCodeCheckBox.setSelected(data.isSkipCode()); 50 | expandFramesCheckBox.setSelected(data.isExpandFrames()); 51 | groovyCodeStyleComboBox.setSelectedItem(data.getCodeStyle()); 52 | } 53 | 54 | public void getData(ASMPluginComponent data) { 55 | data.setSkipDebug(skipDebugCheckBox.isSelected()); 56 | data.setSkipFrames(skipFramesCheckBox.isSelected()); 57 | data.setSkipCode(skipCodeCheckBox.isSelected()); 58 | data.setExpandFrames(expandFramesCheckBox.isSelected()); 59 | data.setCodeStyle((GroovyCodeStyle) groovyCodeStyleComboBox.getSelectedItem()); 60 | } 61 | 62 | public boolean isModified(ASMPluginComponent data) { 63 | if (skipDebugCheckBox.isSelected() != data.isSkipDebug()) return true; 64 | if (skipFramesCheckBox.isSelected() != data.isSkipFrames()) return true; 65 | if (skipCodeCheckBox.isSelected() != data.isSkipCode()) return true; 66 | if (expandFramesCheckBox.isSelected() != data.isExpandFrames()) return true; 67 | if (!groovyCodeStyleComboBox.getSelectedItem().equals(data.getCodeStyle())) return true; 68 | return false; 69 | } 70 | 71 | private void createUIComponents() { 72 | ComboBoxModel model = new EnumComboBoxModel(GroovyCodeStyle.class); 73 | groovyCodeStyleComboBox = new ComboBox(model); 74 | groovyCodeStyleComboBox.setRenderer(new GroovyCodeStyleCellRenderer()); 75 | } 76 | 77 | private static class GroovyCodeStyleCellRenderer implements ListCellRenderer { 78 | private EnumMap labels; 79 | 80 | private GroovyCodeStyleCellRenderer() { 81 | labels = new EnumMap(GroovyCodeStyle.class); 82 | for (GroovyCodeStyle codeStyle : GroovyCodeStyle.values()) { 83 | labels.put(codeStyle, new JLabel(codeStyle.label)); 84 | } 85 | } 86 | 87 | public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean cellHasFocus) { 88 | return labels.get(value); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/org/objectweb/asm/idea/config/GroovyCodeStyle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2011 Cédric Champeau 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * / 17 | */ 18 | 19 | package org.objectweb.asm.idea.config; 20 | /** 21 | * Created by IntelliJ IDEA. 22 | * User: cedric 23 | * Date: 18/01/11 24 | * Time: 22:37 25 | */ 26 | 27 | /** 28 | * Enumeration of Groovy code styles 29 | */ 30 | public enum GroovyCodeStyle { 31 | LEGACY("Legacy bytecode"), 32 | GROOVIFIER_0_2_0("Groovified bytecode"); 33 | 34 | String label; 35 | 36 | GroovyCodeStyle(final String label) { 37 | this.label = label; 38 | } 39 | } 40 | --------------------------------------------------------------------------------