Skip to content

Commit

Permalink
Merge pull request #52 from bibaev/android-studio-support
Browse files Browse the repository at this point in the history
Add android studio support
  • Loading branch information
bibaev authored Jan 11, 2018
2 parents b9a398b + cac9744 commit 1e4184d
Show file tree
Hide file tree
Showing 68 changed files with 439 additions and 1,543 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ apply plugin: 'java'
apply plugin: "kotlin"

group 'com.intellij.debugger.stream'
version '0.1.5'
version '0.1.6'

intellij {
type = 'IC'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,66 +18,86 @@
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.streams.diagnostic.ex.TraceCompilationException;
import com.intellij.debugger.streams.diagnostic.ex.TraceEvaluationException;
import com.intellij.debugger.streams.lib.LibraryManager;
import com.intellij.debugger.streams.lib.LibrarySupport;
import com.intellij.debugger.streams.lib.LibrarySupportProvider;
import com.intellij.debugger.streams.psi.DebuggerPositionResolver;
import com.intellij.debugger.streams.psi.impl.DebuggerPositionResolverImpl;
import com.intellij.debugger.streams.psi.impl.JavaChainTransformerImpl;
import com.intellij.debugger.streams.psi.impl.JavaStreamChainBuilder;
import com.intellij.debugger.streams.psi.impl.StreamChainOption;
import com.intellij.debugger.streams.trace.*;
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl;
import com.intellij.debugger.streams.trace.dsl.impl.java.JavaStatementFactory;
import com.intellij.debugger.streams.trace.impl.JavaTraceExpressionBuilder;
import com.intellij.debugger.streams.trace.impl.TraceResultInterpreterImpl;
import com.intellij.debugger.streams.ui.ChooserOption;
import com.intellij.debugger.streams.ui.impl.ElementChooserImpl;
import com.intellij.debugger.streams.ui.impl.EvaluationAwareTraceWindow;
import com.intellij.debugger.streams.wrapper.StreamChain;
import com.intellij.debugger.streams.wrapper.StreamChainBuilder;
import com.intellij.lang.Language;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiEditorUtil;
import com.intellij.util.PlatformUtils;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.XDebuggerManagerImpl;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
* @author Vitaliy.Bibaev
*/
public class TraceStreamAction extends AnAction {
private static final Logger LOG = Logger.getInstance(TraceStreamAction.class);
private static final boolean IS_ANDROID_STUDIO = "AndroidStudio".equals(PlatformUtils.getPlatformPrefix());

private final DebuggerPositionResolver myPositionResolver = new DebuggerPositionResolverImpl();
private final List<StreamChainBuilder> myChainBuilders =
Collections.singletonList(new JavaStreamChainBuilder(new JavaChainTransformerImpl()));
private final List<SupportedLibrary> mySupportedLibraries =
LibrarySupportProvider.getList().stream().map(SupportedLibrary::new).collect(Collectors.toList());
private final Set<String> mySupportedLanguages = StreamEx.of(mySupportedLibraries).map(x -> x.languageId).toSet();

@Override
public void update(@NotNull AnActionEvent e) {
final XDebugSession session = getCurrentSession(e);
final PsiElement element = session == null ? null : myPositionResolver.getNearestElementToBreakpoint(session);
e.getPresentation().setEnabled(element != null && isChainExists(element));
final Presentation presentation = e.getPresentation();
if (element == null) {
presentation.setVisible(true);
presentation.setEnabled(false);
}
else {
final Language language = element.getLanguage();
if (mySupportedLanguages.contains(language.getID()) && isActionEnabled(language)) {
presentation.setVisible(true);
presentation.setEnabled(isChainExists(element));
}
else {
presentation.setEnabledAndVisible(false);
}
}
}

@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final XDebugSession session = getCurrentSession(e);
Extensions.getExtensions(LibrarySupportProvider.EP_NAME);
final PsiElement element = session == null ? null : myPositionResolver.getNearestElementToBreakpoint(session);

if (element != null && isJdkAtLeast9(session.getProject(), element)) {
Expand All @@ -88,17 +108,18 @@ public void actionPerformed(@NotNull AnActionEvent e) {
}

if (element != null) {
final List<StreamChain> chains = myChainBuilders.stream()
.filter(builder -> builder.isChainExists(element))
.flatMap(builder -> builder.build(element).stream())
final List<StreamChainWithLibrary> chains = mySupportedLibraries.stream()
.filter(library -> library.languageId.equals(element.getLanguage().getID()))
.filter(library -> library.builder.isChainExists(element))
.flatMap(library -> library.builder.build(element).stream().map(x -> new StreamChainWithLibrary(x, library)))
.collect(Collectors.toList());
if (chains.isEmpty()) {
LOG.warn("stream chain is not built");
return;
}

if (chains.size() == 1) {
runTrace(chains.get(0), session);
runTrace(chains.get(0).chain, chains.get(0).library, session);
}
else {
final Editor editor = PsiEditorUtil.Service.getInstance().findEditorByPsiElement(element);
Expand All @@ -107,7 +128,7 @@ public void actionPerformed(@NotNull AnActionEvent e) {
}

new MyStreamChainChooser(editor).show(chains.stream().map(StreamChainOption::new).collect(Collectors.toList()),
provider -> runTrace(provider.getChain(), session));
provider -> runTrace(provider.chain, provider.library, session));
}
}
else {
Expand All @@ -116,26 +137,26 @@ public void actionPerformed(@NotNull AnActionEvent e) {
}

private boolean isChainExists(@NotNull PsiElement element) {
for (final StreamChainBuilder b : myChainBuilders) {
if (b.isChainExists(element)) {
for (final SupportedLibrary library : mySupportedLibraries) {
if (element.getLanguage().getID().equals(library.languageId) && library.builder.isChainExists(element)) {
return true;
}
}

return false;
}

private void runTrace(@NotNull StreamChain chain, @NotNull XDebugSession session) {
private static void runTrace(@NotNull StreamChain chain, @NotNull SupportedLibrary library, @NotNull XDebugSession session) {
final EvaluationAwareTraceWindow window = new EvaluationAwareTraceWindow(session, chain);
ApplicationManager.getApplication().invokeLater(window::show);
final Project project = session.getProject();
final TraceExpressionBuilder expressionBuilder = new JavaTraceExpressionBuilder(project, new DslImpl(new JavaStatementFactory()));
final TraceResultInterpreterImpl resultInterpreter = new TraceResultInterpreterImpl(project);
final TraceExpressionBuilder expressionBuilder = library.createExpressionBuilder(project);
final TraceResultInterpreterImpl resultInterpreter = new TraceResultInterpreterImpl(library.librarySupport.getInterpreterFactory());
final StreamTracer tracer = new EvaluateExpressionTracer(session, expressionBuilder, resultInterpreter);
tracer.trace(chain, new TracingCallback() {
@Override
public void evaluated(@NotNull TracingResult result, @NotNull EvaluationContextImpl context) {
final ResolvedTracingResult resolvedTrace = result.resolve(LibraryManager.getInstance(context.getProject()));
final ResolvedTracingResult resolvedTrace = result.resolve(library.librarySupport.getResolverFactory());
ApplicationManager.getApplication()
.invokeLater(() -> window.setTrace(resolvedTrace, context));
}
Expand All @@ -159,11 +180,15 @@ private void notifyUI(@NotNull String message) {
}

@Nullable
private XDebugSession getCurrentSession(@NotNull AnActionEvent e) {
private static XDebugSession getCurrentSession(@NotNull AnActionEvent e) {
final Project project = e.getProject();
return project == null ? null : XDebuggerManager.getInstance(project).getCurrentSession();
}

private static boolean isActionEnabled(@NotNull Language language) {
return !(IS_ANDROID_STUDIO && language.is(JavaLanguage.INSTANCE));
}

private static boolean isJdkAtLeast9(@NotNull Project project, @NotNull PsiElement element) {
if (element.getLanguage().is(JavaLanguage.INSTANCE)) {
final Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
Expand All @@ -181,4 +206,56 @@ private static class MyStreamChainChooser extends ElementChooserImpl<StreamChain
super(editor);
}
}

private static class SupportedLibrary {
final String languageId;
final StreamChainBuilder builder;
final LibrarySupport librarySupport;
private final LibrarySupportProvider mySupportProvider;

SupportedLibrary(@NotNull LibrarySupportProvider provider) {
languageId = provider.getLanguageId();
builder = provider.getChainBuilder();
librarySupport = provider.getLibrarySupport();
mySupportProvider = provider;
}

TraceExpressionBuilder createExpressionBuilder(@NotNull Project project) {
return mySupportProvider.getExpressionBuilder(project);
}
}

private static class StreamChainWithLibrary {
final StreamChain chain;
final SupportedLibrary library;

StreamChainWithLibrary(@NotNull StreamChain chain, @NotNull SupportedLibrary library) {
this.chain = chain;
this.library = library;
}
}

private static class StreamChainOption implements ChooserOption {
final StreamChain chain;
final SupportedLibrary library;

StreamChainOption(@NotNull StreamChainWithLibrary chain) {
this.chain = chain.chain;
library = chain.library;
}

@NotNull
@Override
public Stream<TextRange> rangeStream() {
return Stream.of(
new TextRange(chain.getQualifierExpression().getTextRange().getStartOffset(),
chain.getTerminationCall().getTextRange().getEndOffset()));
}

@NotNull
@Override
public String getText() {
return chain.getCompactText();
}
}
}
28 changes: 0 additions & 28 deletions src/main/java/com/intellij/debugger/streams/lib/Language.kt

This file was deleted.

25 changes: 0 additions & 25 deletions src/main/java/com/intellij/debugger/streams/lib/Library.kt

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import com.intellij.debugger.streams.trace.dsl.Dsl
* @author Vitaliy.Bibaev
*/
interface LibrarySupport {
val description: Library

fun createHandlerFactory(dsl: Dsl): HandlerFactory
val interpreterFactory: InterpreterFactory
val resolverFactory: ResolverFactory
Expand Down
Loading

0 comments on commit 1e4184d

Please sign in to comment.