From fa5d7c4365834c2d0583cdc8daa8317a639ddbc1 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 17 Jan 2014 13:33:31 +0400 Subject: [PATCH] EA-52654 - NPE: TemplateState.setCurrentVariableNumber --- .../template/impl/TemplateManagerImpl.java | 27 ++++++------ .../template/impl/TemplateState.java | 44 ++++++++++--------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java index 41cfbad7323e..05ecfadee46d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -80,11 +80,11 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo Editor editor = event.getEditor(); if (editor.getProject() != null && editor.getProject() != myProject) return; if (myProject.isDisposed() || !myProject.isOpen()) return; - TemplateState tState = getTemplateState(editor); - if (tState != null) { - tState.gotoEnd(); + TemplateState state = getTemplateState(editor); + if (state != null) { + state.gotoEnd(); } - editor.putUserData(TEMPLATE_STATE_KEY, null); + clearTemplateState(editor); } }; EditorFactory.getInstance().addEditorFactoryListener(myEditorFactoryListener, myProject); @@ -108,8 +108,8 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo }); } - private static void disposeState(final TemplateState tState) { - Disposer.dispose(tState); + private static void disposeState(@NotNull TemplateState state) { + Disposer.dispose(state); } @Override @@ -123,11 +123,11 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo } @Nullable - public static TemplateState getTemplateState(Editor editor) { + public static TemplateState getTemplateState(@NotNull Editor editor) { return editor.getUserData(TEMPLATE_STATE_KEY); } - void clearTemplateState(final Editor editor) { + static void clearTemplateState(@NotNull Editor editor) { TemplateState prevState = getTemplateState(editor); if (prevState != null) { disposeState(prevState); @@ -135,7 +135,7 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo editor.putUserData(TEMPLATE_STATE_KEY, null); } - private TemplateState initTemplateState(final Editor editor) { + private TemplateState initTemplateState(@NotNull Editor editor) { clearTemplateState(editor); TemplateState state = new TemplateState(myProject, editor); Disposer.register(this, state); @@ -379,7 +379,7 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo final Document document = editor.getDocument(); final CharSequence text = document.getCharsSequence(); - if (template2argument == null || template2argument.size() == 0) { + if (template2argument == null || template2argument.isEmpty()) { return null; } if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), myProject)) { @@ -407,14 +407,13 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo @Nullable Character shortcutChar, TemplateSettings settings, boolean hasArgument) { - String key; List candidates = Collections.emptyList(); for (int i = settings.getMaxKeyLength(); i >= 1; i--) { int wordStart = caretOffset - i; if (wordStart < 0) { continue; } - key = text.subSequence(wordStart, caretOffset).toString(); + String key = text.subSequence(wordStart, caretOffset).toString(); if (Character.isJavaIdentifierStart(key.charAt(0))) { if (wordStart > 0 && Character.isJavaIdentifierPart(text.charAt(wordStart - 1))) { continue; @@ -519,7 +518,7 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo final TemplateContextType[] typeCollection = getAllContextTypes(); LinkedList userDefinedExtensionsFirst = new LinkedList(); for (TemplateContextType contextType : typeCollection) { - if (contextType.getClass().getName().startsWith("com.intellij.codeInsight.template")) { + if (contextType.getClass().getName().startsWith(Template.class.getPackage().getName())) { userDefinedExtensionsFirst.addLast(contextType); } else { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 2bcf02b50abc..1ce2e351b3ed 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -93,6 +93,7 @@ public class TemplateState implements Disposable { private boolean myFinished; @Nullable private PairProcessor myProcessor; private boolean mySelectionCalculated = false; + private boolean myStarted; public TemplateState(@NotNull Project project, final Editor editor) { myProject = project; @@ -134,32 +135,27 @@ public class TemplateState implements Disposable { final LookupImpl lookup = myEditor != null ? (LookupImpl)LookupManager.getActiveLookup(myEditor) : null; if (lookup != null) { lookup.performGuardedChange(runnable); - } else { + } + else { runnable.run(); } } } }; - myDocument.addDocumentListener(myEditorDocumentListener); - CommandProcessor.getInstance().addCommandListener(myCommandListener); + myDocument.addDocumentListener(myEditorDocumentListener, this); + CommandProcessor.getInstance().addCommandListener(myCommandListener, this); } @Override public synchronized void dispose() { - if (myEditorDocumentListener != null) { - myDocument.removeDocumentListener(myEditorDocumentListener); - myEditorDocumentListener = null; - } - if (myCommandListener != null) { - CommandProcessor.getInstance().removeCommandListener(myCommandListener); - myCommandListener = null; - } + myEditorDocumentListener = null; + myCommandListener = null; myProcessor = null; //Avoid the leak of the editor - releaseEditor(); + releaseAll(); myDocument = null; } @@ -176,7 +172,7 @@ public class TemplateState implements Disposable { private void setCurrentVariableNumber(int variableNumber) { myCurrentVariableNumber = variableNumber; - final boolean isFinished = variableNumber < 0; + final boolean isFinished = isFinished(); ((DocumentEx)myDocument).setStripTrailingSpacesEnabled(isFinished); myCurrentSegmentNumber = isFinished ? -1 : getCurrentSegmentNumber(); } @@ -262,9 +258,11 @@ public class TemplateState implements Disposable { } } - public void start(TemplateImpl template, + public void start(@NotNull TemplateImpl template, @Nullable final PairProcessor processor, @Nullable Map predefinedVarValues) { + LOG.assertTrue(!myStarted, "Already started"); + myStarted = true; myTemplate = template; PsiDocumentManager.getInstance(myProject).commitAllDocuments(); @@ -328,7 +326,7 @@ public class TemplateState implements Disposable { } } - private void processAllExpressions(final TemplateImpl template) { + private void processAllExpressions(@NotNull final TemplateImpl template) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { @@ -365,7 +363,7 @@ public class TemplateState implements Disposable { }); } - public void doReformat(final TextRange range) { + private void doReformat(final TextRange range) { RangeMarker rangeMarker = null; if (range != null) { rangeMarker = myDocument.createRangeMarker(range); @@ -876,14 +874,20 @@ public class TemplateState implements Disposable { } } + boolean isDisposed() { + return myDocument == null; + } + private void cleanupTemplateState(boolean brokenOff) { final Editor editor = myEditor; fireBeforeTemplateFinished(); int oldVar = myCurrentVariableNumber; - setCurrentVariableNumber(-1); currentVariableChanged(oldVar); - ((TemplateManagerImpl)TemplateManager.getInstance(myProject)).clearTemplateState(editor); - fireTemplateFinished(brokenOff); + if (!isDisposed()) { + setCurrentVariableNumber(-1); + TemplateManagerImpl.clearTemplateState(editor); + fireTemplateFinished(brokenOff); + } myListeners.clear(); myProject = null; }