From 9f156017ac998e55cdca6c888a794bfcce63d734 Mon Sep 17 00:00:00 2001 From: Michail Plushnikov Date: Sat, 2 Nov 2013 21:43:19 +0100 Subject: [PATCH] Fix some of stackoverflow exceptions --- .../plugin/extension/UserMapKeys.java | 36 ++++---- .../plugin/processor/AbstractProcessor.java | 10 ++- .../intellij/plugin/processor/Processor.java | 2 + .../clazz/AbstractClassProcessor.java | 2 +- .../clazz/BuilderInnerClassProcessor.java | 2 +- .../processor/clazz/BuilderProcessor.java | 21 ++--- .../processor/clazz/SetterProcessor.java | 2 +- .../field/AbstractFieldProcessor.java | 2 +- .../processor/field/GetterFieldProcessor.java | 2 +- .../processor/field/SetterFieldProcessor.java | 2 +- .../method/AbstractMethodProcessor.java | 2 +- .../BuilderMethodInnerClassProcessor.java | 2 +- .../plugin/provider/LombokAnnotator.java | 36 -------- .../provider/LombokAugmentProvider.java | 85 +++++++++++++------ .../src/main/resources/META-INF/plugin.xml | 9 +- 15 files changed, 115 insertions(+), 100 deletions(-) delete mode 100644 lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAnnotator.java diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/extension/UserMapKeys.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/extension/UserMapKeys.java index 941bae5b9..2ffee4449 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/extension/UserMapKeys.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/extension/UserMapKeys.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.concurrent.TimeUnit; public class UserMapKeys { @@ -18,7 +19,7 @@ public class UserMapKeys { public static final Key READ_KEY = Key.create(LOMBOK_HAS_IMPLICIT_READ_PROPERTY); public static final Key WRITE_KEY = Key.create(LOMBOK_HAS_IMPLICIT_WRITE_PROPERTY); - public static final Key HAS_LOMBOK_KEY = Key.create(LOMBOK_IS_PRESENT_PROPERTY); + public static final Key HAS_LOMBOK_KEY = Key.create(LOMBOK_IS_PRESENT_PROPERTY); public static void removeAllUsagesFrom(@NotNull UserDataHolder element) { if (null != element.getUserData(READ_KEY)) { @@ -44,27 +45,30 @@ public static void addWriteUsageFor(@NotNull UserDataHolder element) { element.putUserData(WRITE_KEY, Boolean.TRUE); } - public static void addLombokPresentFor(@NotNull UserDataHolder element) { - element.putUserData(HAS_LOMBOK_KEY, Boolean.TRUE); + public static void addReadUsageFor(@NotNull Collection elements) { + for (UserDataHolder element : elements) { + addReadUsageFor(element); + } } - public static void addLombokNotPresentFor(@NotNull UserDataHolder element) { - element.putUserData(HAS_LOMBOK_KEY, Boolean.FALSE); - } + private static final long PRESENT_TIME = TimeUnit.SECONDS.toNanos(1); + + private static class LombokPresentData { + private final boolean present; + private final long nanoTime; - public static boolean containLombok(@NotNull UserDataHolder element) { - Boolean userData = element.getUserData(HAS_LOMBOK_KEY); - return Boolean.TRUE.equals(userData); + private LombokPresentData(boolean present) { + this.present = present; + this.nanoTime = System.nanoTime(); + } } - public static boolean mayContainLombok(@NotNull UserDataHolder element) { - Boolean userData = element.getUserData(HAS_LOMBOK_KEY); - return null==userData||Boolean.TRUE.equals(userData); + public static void updateLombokPresent(@NotNull UserDataHolder element, boolean isPresent) { + element.putUserData(HAS_LOMBOK_KEY, new LombokPresentData(isPresent)); } - public static void addReadUsageFor(@NotNull Collection elements) { - for (UserDataHolder element : elements) { - addReadUsageFor(element); - } + public static boolean isLombokPossiblePresent(@NotNull UserDataHolder element) { + LombokPresentData userData = element.getUserData(HAS_LOMBOK_KEY); + return null == userData || (userData.nanoTime < System.nanoTime() - PRESENT_TIME) || userData.present; } } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/AbstractProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/AbstractProcessor.java index 9016f0538..ac95047de 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/AbstractProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/AbstractProcessor.java @@ -28,7 +28,7 @@ public abstract class AbstractProcessor implements Processor { /** * Kind of output elements this processor supports */ - private final Class supportedClass; + private final Class supportedClass; /** * Constructor for all Lombok-Processors @@ -36,7 +36,7 @@ public abstract class AbstractProcessor implements Processor { * @param supportedAnnotationClass annotation this processor supports * @param supportedClass kind of output elements this processor supports */ - protected AbstractProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected AbstractProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { this.supportedAnnotationClass = supportedAnnotationClass; this.supportedAnnotation = supportedAnnotationClass.getName(); this.supportedClass = supportedClass; @@ -54,6 +54,12 @@ public final Class getSupportedAnnotationClass() { return supportedAnnotationClass; } + @NotNull + @Override + public final Class getSupportedClass() { + return supportedClass; + } + public boolean acceptAnnotation(@NotNull PsiAnnotation psiAnnotation, @NotNull Class type) { final String annotationName = StringUtil.notNullize(psiAnnotation.getQualifiedName()).trim(); return supportedAnnotation.equals(annotationName) && canProduce(type); diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/Processor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/Processor.java index 45bb9e904..78d6e7df9 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/Processor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/Processor.java @@ -22,6 +22,8 @@ public interface Processor { Class getSupportedAnnotationClass(); + Class getSupportedClass(); + Collection verifyAnnotation(@NotNull PsiAnnotation psiAnnotation); diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/AbstractClassProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/AbstractClassProcessor.java index 0e38a9cc3..15ea1e433 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/AbstractClassProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/AbstractClassProcessor.java @@ -33,7 +33,7 @@ */ public abstract class AbstractClassProcessor extends AbstractProcessor implements ClassProcessor { - protected AbstractClassProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected AbstractClassProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderInnerClassProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderInnerClassProcessor.java index f531dd623..4dc350bd9 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderInnerClassProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderInnerClassProcessor.java @@ -36,7 +36,7 @@ public BuilderInnerClassProcessor() { super(Builder.class, PsiClass.class); } - protected BuilderInnerClassProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected BuilderInnerClassProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderProcessor.java index dab3dc126..bcda3af61 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/BuilderProcessor.java @@ -45,16 +45,17 @@ protected void processIntern(@NotNull PsiClass psiClass, @NotNull PsiAnnotation String innerClassName = BuilderUtil.createBuilderClassName(psiAnnotation, psiClass); PsiClass innerClassByName = PsiClassUtil.getInnerClassByName(psiClass, innerClassName); assert innerClassByName != null; // BuilderInnerClassProcessor should run first - - final String builderMethodName = BuilderUtil.createBuilderMethodName(psiAnnotation); - if (!PsiMethodUtil.hasMethodByName(PsiClassUtil.collectClassMethodsIntern(psiClass), builderMethodName)) { - LombokLightMethodBuilder method = new LombokLightMethodBuilder(psiClass.getManager(), builderMethodName) - .withMethodReturnType(PsiClassUtil.getTypeWithGenerics(innerClassByName)) - .withContainingClass(psiClass) - .withNavigationElement(psiAnnotation); - method.withModifier(PsiModifier.STATIC); - method.withModifier(PsiModifier.PUBLIC); - target.add(method); + if (null != innerClassByName) { + final String builderMethodName = BuilderUtil.createBuilderMethodName(psiAnnotation); + if (!PsiMethodUtil.hasMethodByName(PsiClassUtil.collectClassMethodsIntern(psiClass), builderMethodName)) { + LombokLightMethodBuilder method = new LombokLightMethodBuilder(psiClass.getManager(), builderMethodName) + .withMethodReturnType(PsiClassUtil.getTypeWithGenerics(innerClassByName)) + .withContainingClass(psiClass) + .withNavigationElement(psiAnnotation); + method.withModifier(PsiModifier.STATIC); + method.withModifier(PsiModifier.PUBLIC); + target.add(method); + } } } } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java index 595647bb4..c3062c76a 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/SetterProcessor.java @@ -36,7 +36,7 @@ public SetterProcessor() { this(Setter.class, PsiMethod.class); } - protected SetterProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected SetterProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/AbstractFieldProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/AbstractFieldProcessor.java index b8520add7..bc3d3163d 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/AbstractFieldProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/AbstractFieldProcessor.java @@ -30,7 +30,7 @@ */ public abstract class AbstractFieldProcessor extends AbstractProcessor implements FieldProcessor { - protected AbstractFieldProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected AbstractFieldProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java index 1d217df13..c752d5821 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/GetterFieldProcessor.java @@ -36,7 +36,7 @@ public GetterFieldProcessor() { super(Getter.class, PsiMethod.class); } - protected GetterFieldProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected GetterFieldProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java index dc051fe1f..0aa6b1198 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/field/SetterFieldProcessor.java @@ -38,7 +38,7 @@ public SetterFieldProcessor() { this(Setter.class, PsiMethod.class); } - protected SetterFieldProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected SetterFieldProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/AbstractMethodProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/AbstractMethodProcessor.java index 14788e965..ed0a82c4a 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/AbstractMethodProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/AbstractMethodProcessor.java @@ -27,7 +27,7 @@ */ public abstract class AbstractMethodProcessor extends AbstractProcessor implements MethodProcessor { - protected AbstractMethodProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected AbstractMethodProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/BuilderMethodInnerClassProcessor.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/BuilderMethodInnerClassProcessor.java index d1c344fb1..5cd632695 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/BuilderMethodInnerClassProcessor.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/processor/method/BuilderMethodInnerClassProcessor.java @@ -36,7 +36,7 @@ public BuilderMethodInnerClassProcessor() { super(Builder.class, PsiClass.class); } - protected BuilderMethodInnerClassProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { + protected BuilderMethodInnerClassProcessor(@NotNull Class supportedAnnotationClass, @NotNull Class supportedClass) { super(supportedAnnotationClass, supportedClass); } diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAnnotator.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAnnotator.java deleted file mode 100644 index 5cbd7b8ad..000000000 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAnnotator.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.plushnikov.intellij.plugin.provider; - -import com.intellij.codeInsight.AnnotationUtil; -import com.intellij.lang.annotation.AnnotationHolder; -import com.intellij.lang.annotation.Annotator; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiModifierListOwner; -import de.plushnikov.intellij.plugin.extension.LombokProcessorExtensionPoint; -import de.plushnikov.intellij.plugin.extension.UserMapKeys; -import org.jetbrains.annotations.NotNull; - -//PsiTreeChangeListener //DaemonCodeAnalyzer.getInstance(project).updateVisibleHighlighters(editor) -public class LombokAnnotator implements Annotator { - private static final Logger log = Logger.getInstance(LombokAnnotator.class.getName()); - - @Override - public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { - if (element instanceof PsiModifierListOwner) { - PsiModifierListOwner psiModifierList = (PsiModifierListOwner) element; - PsiFile containingFile = psiModifierList.getContainingFile(); - if (null != containingFile && !UserMapKeys.containLombok(containingFile)) { - - PsiAnnotation psiAnnotation = AnnotationUtil.findAnnotation(psiModifierList, LombokProcessorExtensionPoint.getAllOfProcessedLombokAnnotation(), true); - if (null != psiAnnotation) { - UserMapKeys.addLombokPresentFor(containingFile); - } - if (log.isDebugEnabled()) { - log.debug(String.format("Processed file %s Lombok is %s", containingFile.getName(), null != psiAnnotation)); - } - } - } - } -} diff --git a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java index 6c3488664..e3ec741ea 100644 --- a/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java +++ b/lombok-plugin/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java @@ -3,6 +3,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; @@ -15,10 +16,13 @@ import de.plushnikov.intellij.plugin.util.PsiClassUtil; import org.jetbrains.annotations.NotNull; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Scanner; /** * Provides support for lombok generated elements @@ -51,42 +55,73 @@ public List getAugments(@NotNull PsiElement elemen return emptyResult; } - final PsiClass psiClass = (PsiClass) element; - if (log.isDebugEnabled()) { - log.debug(String.format("Process class %s with LombokAugmentProvider for type %s", psiClass.getQualifiedName(), type.getName())); + boolean isLombokPresent = UserMapKeys.isLombokPossiblePresent(element); + if (!isLombokPresent) { + if (log.isDebugEnabled()) { + log.debug(String.format("Skipped call for type: %s class: %s", type, ((PsiClass) element).getQualifiedName())); + } + return Collections.emptyList(); } - final PsiFile containingFile = psiClass.getContainingFile(); - if (UserMapKeys.mayContainLombok(containingFile)) { - if (!UserMapKeys.containLombok(containingFile)) { - if (containingFile.getText().contains("lombok.")) { - UserMapKeys.addLombokPresentFor(containingFile); - } else { - UserMapKeys.addLombokNotPresentFor(containingFile); - } + return process(type, project, (PsiClass) element); + } + + private List process(Class type, Project project, PsiClass psiClass) { + boolean isLombokPossiblePresent = true; + try { + isLombokPossiblePresent = verifyLombokPresent(psiClass); + } catch (IOException ex) { + log.warn("Exception durcing check for Lombok", ex); + } + UserMapKeys.updateLombokPresent(psiClass, isLombokPossiblePresent); + + if (isLombokPossiblePresent) { + if (log.isDebugEnabled()) { + log.debug(String.format("Process call for type: %s class: %s", type, psiClass.getQualifiedName())); } - if (UserMapKeys.containLombok(containingFile)) { - cleanAttributeUsage(psiClass); + cleanAttributeUsage(psiClass); - final List result = new ArrayList(); - for (Processor processor : LombokProcessorExtensionPoint.EP_NAME.getExtensions()) { - if (processor.canProduce(type) && processor.isEnabled(project)) { - result.addAll((Collection) processor.process(psiClass)); - } - } - return result; - }else{ - if (log.isDebugEnabled()) { - log.debug(String.format("Skipped file %s", containingFile.getName())); + final List result = new ArrayList(); + for (Processor processor : LombokProcessorExtensionPoint.EP_NAME.getExtensions()) { + if (processor.canProduce(type) && processor.isEnabled(project)) { + result.addAll((Collection) processor.process(psiClass)); } } + return result; } else { if (log.isDebugEnabled()) { - log.debug(String.format("Skipped file %s quickly", containingFile.getName())); + log.debug(String.format("Skipped call for type: %s class: %s", type, psiClass.getQualifiedName())); + } + } + return Collections.emptyList(); + } + + private boolean verifyLombokPresent(PsiClass psiClass) throws IOException { + boolean isLombokPossiblePresent = true; + final PsiFile containingFile = psiClass.getContainingFile(); + if (null != containingFile) { + VirtualFile virtualFile = containingFile.getVirtualFile(); + if (null != virtualFile) { + InputStream inputStream = null; + try { + inputStream = virtualFile.getInputStream(); + Scanner scanner = new Scanner(inputStream); + while (scanner.hasNextLine()) { + final String lineFromFile = scanner.nextLine(); + isLombokPossiblePresent = lineFromFile.contains("lombok."); + if (isLombokPossiblePresent) { + break; + } + } + } finally { + if (null != inputStream) { + inputStream.close(); + } + } } } - return emptyResult; + return isLombokPossiblePresent; } protected void cleanAttributeUsage(PsiClass psiClass) { diff --git a/lombok-plugin/src/main/resources/META-INF/plugin.xml b/lombok-plugin/src/main/resources/META-INF/plugin.xml index b44a1fc63..41d0d7e1a 100644 --- a/lombok-plugin/src/main/resources/META-INF/plugin.xml +++ b/lombok-plugin/src/main/resources/META-INF/plugin.xml @@ -4,7 +4,7 @@ Lombok Plugin Michail Plushnikov - 0.7.1 + 0.7.2 - - @@ -83,6 +81,11 @@ +
  • 0.7.2 +
      +
    1. Fix multiple stackoverflow exceptions
    2. +
    +
  • 0.7.1
    1. Some performance optimizations