diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskBase.java b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskBase.java index ad73ef77b92d..8d86241f2ec3 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskBase.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -45,7 +45,7 @@ public abstract class BuildArtifactsBeforeRunTaskBase children = element.getChildren(myElementName); final ArtifactPointerManager pointerManager = ArtifactPointerManager.getInstance(myProject); @@ -62,7 +62,7 @@ public abstract class BuildArtifactsBeforeRunTaskBase pointers = new THashSet<>(); for (Artifact artifact : artifacts) { @@ -111,7 +111,7 @@ public abstract class BuildArtifactsBeforeRunTaskProviderBase)task.getArtifactPointers()) { if (pointer.getArtifact() != null) { return true; @@ -121,9 +121,9 @@ public abstract class BuildArtifactsBeforeRunTaskProviderBase result = Ref.create(false); final Semaphore finished = new Semaphore(); diff --git a/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java b/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java index a6f9ca169927..5820e32b81ed 100644 --- a/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java +++ b/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java @@ -106,16 +106,7 @@ public class CompileStepBeforeRun extends BeforeRunTaskProvider { - ref.referenceName ?: return emptyList() + if (ref.referenceName == null) return emptyList() + val fieldRequests = CreateFieldRequests(ref).collectRequests() val extensions = EP_NAME.extensions - return generateRequests(ref).flatMap { (clazz, request) -> + return fieldRequests.flatMap { (clazz, request) -> extensions.flatMap { ext -> ext.createAddFieldActions(clazz, request) } } } -private fun generateRequests(ref: PsiReferenceExpression): List> { - val (instanceContext, staticContext) = collectTargets(ref) ?: return emptyList() +private class CreateFieldRequests(val myRef: PsiReferenceExpression) { - val instanceFieldRequests = instanceContext.filter { - it.classKind !in STATIC_ONLY - }.map { - it to generateRequest(ref, it, false) - } - val staticFieldRequests = staticContext.map { - it to generateRequest(ref, it, true) + private val requests = LinkedHashMap() + + fun collectRequests(): Map { + doCollectRequests() + return requests } - return instanceFieldRequests + staticFieldRequests + private fun doCollectRequests() { + val qualifier = myRef.qualifierExpression + + if (qualifier != null) { + val instanceClass = resolveClassInClassTypeOnly(qualifier.type) + if (instanceClass != null) { + processHierarchy(instanceClass) + } + else { + val staticClass = (qualifier as? PsiJavaCodeReferenceElement)?.resolve() as? PsiClass + if (staticClass != null) { + processClass(staticClass, true) + } + } + } + else { + val baseClass = extractBaseClassFromSwitchStatement() + if (baseClass != null) { + processHierarchy(baseClass) + } + else { + processOuterAndImported() + } + } + } + + private fun extractBaseClassFromSwitchStatement(): PsiClass? { + val parent = myRef.parent as? PsiSwitchLabelStatement ?: return null + val switchStatement = parent.parentOfType() ?: return null + return resolveClassInClassTypeOnly(switchStatement.expression?.type) + } + + private fun processHierarchy(baseClass: PsiClass) { + for (clazz in hierarchy(baseClass)) { + processClass(clazz, false) + } + } + + private fun processOuterAndImported() { + val inStaticContext = myRef.isInStaticContext() + for (outerClass in collectOuterClasses(myRef)) { + processClass(outerClass, inStaticContext) + } + for (imported in collectOnDemandImported(myRef)) { + processClass(imported, true) + } + } + + private fun processClass(target: JvmClass, staticContext: Boolean) { + if (!staticContext && target.classKind in STATIC_ONLY) return + val modifiers = mutableSetOf() + + if (staticContext) { + modifiers += JvmModifier.STATIC + } + + if (shouldCreateFinalField(myRef, target)) { + modifiers += JvmModifier.FINAL + } + + val ownerClass = myRef.parentOfType() + val visibility = computeVisibility(myRef.project, ownerClass, target) + if (visibility != null) { + modifiers += visibility + } + + val request = CreateFieldFromJavaUsageRequest( + modifiers = modifiers, + reference = myRef, + useAnchor = target.toJavaClassOrNull() == ownerClass, + constant = false + ) + requests[target] = request + } } private val STATIC_ONLY = arrayOf(JvmClassKind.INTERFACE, JvmClassKind.ANNOTATION) -private fun generateRequest(ref: PsiReferenceExpression, target: JvmClass, static: Boolean): CreateFieldRequest { - val modifiers = mutableSetOf() - - if (static) { - modifiers += JvmModifier.STATIC - } - - if (shouldCreateFinalField(ref, target)) { - modifiers += JvmModifier.FINAL - } - - val ownerClass = getParentOfType(ref, PsiClass::class.java) - val visibility = computeVisibility(ref.project, ownerClass, target) - if (visibility != null) { - modifiers += visibility - } - - return CreateFieldFromJavaUsageRequest( - modifiers = modifiers, - reference = ref, - useAnchor = target.toJavaClassOrNull() == ownerClass, - constant = false - ) -} - -private typealias Couple = Pair - -private fun collectTargets(ref: PsiReferenceExpression): Couple>? { - var baseClass: PsiClass? = null - var inStaticContext = false - val qualifier: PsiExpression? = ref.qualifierExpression - - if (qualifier == null) { - val parent = ref.parent - if (parent is PsiSwitchLabelStatement) { - val switchStatement = getParentOfType(parent, PsiSwitchStatement::class.java) - if (switchStatement != null) { - baseClass = resolveClassInClassTypeOnly(switchStatement.expression?.type) - } - } - if (baseClass == null) { - return collectOuterAndImported(ref) - } - } - else { - baseClass = resolveClassInClassTypeOnly(qualifier.type) - if (baseClass == null) { - inStaticContext = true - baseClass = (qualifier as? PsiJavaCodeReferenceElement)?.resolve() as? PsiClass - } - } - baseClass ?: return null - if (inStaticContext) { - return Pair(emptyList(), listOf(baseClass)) - } - val hierarchy = hierarchy(baseClass).filter { it !is PsiTypeParameter } - return Pair(hierarchy, emptyList()) -} - -private fun collectOuterAndImported(place: PsiElement): Couple> { - val inStaticContext = place.parentOfType()?.hasModifierProperty(PsiModifier.STATIC) ?: false - val outerClasses = collectOuterClasses(place) - val importedClasses = collectOnDemandImported(place) - return if (inStaticContext) Pair(emptyList(), outerClasses + importedClasses) else Pair(outerClasses, importedClasses) -} - -private fun collectOuterClasses(place: PsiElement): List { - val result = mutableListOf() - for (clazz in place.parentsOfType()) { - result.add(clazz) - if (clazz.hasModifierProperty(PsiModifier.STATIC)) break - } - return result -} - /** * Given unresolved unqualified reference, * this reference could be resolved into static member if some class which has it's members imported. @@ -155,41 +142,7 @@ private fun collectOnDemandImported(place: PsiElement): List { return onDemandImports.mapNotNull { it.resolveTargetClass() } } -private fun hierarchy(clazz: PsiClass): Collection { - val result = LinkedHashSet() - val queue = LinkedList() - queue.add(clazz) - while (queue.isNotEmpty()) { - val current = queue.removeFirst() - if (result.add(current)) { - queue.addAll(current.supers) - } - } - return result -} - private fun shouldCreateFinalField(ref: PsiReferenceExpression, targetClass: JvmClass): Boolean { val javaClass = targetClass.toJavaClassOrNull() ?: return false return CreateFieldFromUsageFix.shouldCreateFinalMember(ref, javaClass) } - -private fun computeVisibility(project: Project, ownerClass: PsiClass?, targetClass: JvmClass): JvmModifier? { - if (targetClass.classKind == JvmClassKind.INTERFACE || targetClass.classKind == JvmClassKind.ANNOTATION) return JvmModifier.PUBLIC - if (ownerClass != null) { - targetClass.toJavaClassOrNull()?.let { javaClass -> - if (javaClass == ownerClass || PsiTreeUtil.isAncestor(javaClass, ownerClass, false)) { - return JvmModifier.PRIVATE - } - } - } - val setting = CodeStyleSettingsManager.getSettings(project).getCustomSettings(JavaCodeStyleSettings::class.java).VISIBILITY - if (setting == VisibilityUtil.ESCALATE_VISIBILITY) { - return null // TODO - } - else if (setting == PsiModifier.PACKAGE_LOCAL) { - return JvmModifier.PACKAGE_LOCAL - } - else { - return JvmModifier.valueOf(setting.toUpperCase()) - } -} diff --git a/java/java-impl/src/com/intellij/lang/java/request/createFromUsageUtils.kt b/java/java-impl/src/com/intellij/lang/java/request/createFromUsageUtils.kt new file mode 100644 index 000000000000..7c5ffaea2c7d --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/request/createFromUsageUtils.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.lang.java.request + +import com.intellij.lang.java.actions.toJavaClassOrNull +import com.intellij.lang.jvm.JvmClass +import com.intellij.lang.jvm.JvmClassKind +import com.intellij.lang.jvm.JvmModifier +import com.intellij.openapi.project.Project +import com.intellij.psi.* +import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import com.intellij.psi.codeStyle.JavaCodeStyleSettings +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.psi.util.parentOfType +import com.intellij.psi.util.parents +import com.intellij.psi.util.parentsOfType +import com.intellij.util.VisibilityUtil +import java.util.* +import kotlin.collections.ArrayList + +internal fun PsiExpression.isInStaticContext(): Boolean { + return isWithinStaticMember() || isWithinConstructorCall() +} + +internal fun PsiExpression.isWithinStaticMember(): Boolean { + return parentOfType()?.hasModifierProperty(PsiModifier.STATIC) ?: false +} + +//usages inside delegating constructor call +internal fun PsiExpression.isWithinConstructorCall(): Boolean { + val owner = parentOfType() as? PsiMethod ?: return false + if (!owner.isConstructor) return false + + val parent = parents().firstOrNull { it !is PsiExpression } as? PsiExpressionList ?: return false + val grandParent = parent.parent as? PsiMethodCallExpression ?: return false + + val calleText = grandParent.methodExpression.text + return calleText == PsiKeyword.SUPER || calleText == PsiKeyword.THIS +} + +internal fun computeVisibility(project: Project, ownerClass: PsiClass?, targetClass: JvmClass): JvmModifier? { + if (targetClass.classKind == JvmClassKind.INTERFACE || targetClass.classKind == JvmClassKind.ANNOTATION) return JvmModifier.PUBLIC + if (ownerClass != null) { + targetClass.toJavaClassOrNull()?.let { javaClass -> + if (javaClass == ownerClass || PsiTreeUtil.isAncestor(javaClass, ownerClass, false)) { + return JvmModifier.PRIVATE + } + } + } + val setting = CodeStyleSettingsManager.getSettings(project).getCustomSettings(JavaCodeStyleSettings::class.java).VISIBILITY + if (setting == VisibilityUtil.ESCALATE_VISIBILITY) { + return null // TODO + } + else if (setting == PsiModifier.PACKAGE_LOCAL) { + return JvmModifier.PACKAGE_LOCAL + } + else { + return JvmModifier.valueOf(setting.toUpperCase()) + } +} + +internal fun collectOuterClasses(place: PsiElement): List { + val result = ArrayList() + for (clazz in place.parentsOfType()) { + result.add(clazz) + if (clazz.hasModifierProperty(PsiModifier.STATIC)) break + } + return result +} + +internal fun hierarchy(clazz: PsiClass): List { // TODO implementation based on JvmClasses + val result = LinkedHashSet() + val queue = LinkedList() + queue.add(clazz) + while (queue.isNotEmpty()) { + val current = queue.removeFirst() + if (result.add(current)) { + queue.addAll(current.supers) + } + } + return result.filter { it !is PsiTypeParameter } +} diff --git a/java/java-impl/src/com/intellij/psi/util/psiTreeUtil.kt b/java/java-impl/src/com/intellij/psi/util/psiTreeUtil.kt index a9221c950e37..e7021d3a5f0f 100644 --- a/java/java-impl/src/com/intellij/psi/util/psiTreeUtil.kt +++ b/java/java-impl/src/com/intellij/psi/util/psiTreeUtil.kt @@ -16,15 +16,17 @@ package com.intellij.psi.util import com.intellij.psi.PsiElement +import kotlin.reflect.KClass -inline fun PsiElement.parentOfType(): T? { - return PsiTreeUtil.getParentOfType(this, T::class.java) +inline fun PsiElement.parentOfType(): T? = parentOfType(T::class) + +fun PsiElement.parentOfType(vararg classes: KClass): T? { + return PsiTreeUtil.getParentOfType(this, *classes.map { it.java }.toTypedArray()) } -inline fun PsiElement?.parentsOfType(): Sequence { - return parentsOfType(T::class.java) -} -fun PsiElement?.parentsOfType(clazz: Class): Sequence { - return generateSequence(this) { it.parent }.filterIsInstance(clazz) -} +inline fun PsiElement.parentsOfType(): Sequence = parentsOfType(T::class.java) + +fun PsiElement.parentsOfType(clazz: Class): Sequence = parents().filterIsInstance(clazz) + +fun PsiElement.parents(): Sequence = generateSequence(this) { it.parent } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java index 1356f057c926..fd100352fc09 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingTest.java @@ -60,6 +60,7 @@ import com.intellij.psi.xml.XmlToken; import com.intellij.psi.xml.XmlTokenType; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.VfsTestUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.ui.UIUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -196,10 +197,10 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase { } finally { PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); - VirtualFile file = FileDocumentManager.getInstance().getFile(e.getDocument()); + VirtualFile file = ObjectUtils.notNull(FileDocumentManager.getInstance().getFile(e.getDocument())); FileEditorManager.getInstance(getProject()).closeFile(file); VfsTestUtil.deleteFile(file); - VirtualFile file2 = FileDocumentManager.getInstance().getFile(e2.getDocument()); + VirtualFile file2 = ObjectUtils.notNull(FileDocumentManager.getInstance().getFile(e2.getDocument())); FileEditorManager.getInstance(getProject()).closeFile(file2); VfsTestUtil.deleteFile(file2); } diff --git a/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java b/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java index 9d35e9de69b3..b17bdadd9f74 100644 --- a/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java @@ -248,7 +248,7 @@ public class RootsChangedTest extends ModuleTestCase { rootModelB.addLibraryEntry(libraryA); rootModelA.addInvalidLibrary("Q", libraryTable.getTableLevel()); rootModelB.addInvalidLibrary("Q", libraryTable.getTableLevel()); - ModifiableRootModel[] rootModels = new ModifiableRootModel[]{rootModelA, rootModelB}; + ModifiableRootModel[] rootModels = {rootModelA, rootModelB}; if (rootModels.length > 0) { ModifiableModelCommitter.multiCommit(rootModels, ModuleManager.getInstance(rootModels[0].getProject()).getModifiableModel()); } @@ -317,7 +317,7 @@ public class RootsChangedTest extends ModuleTestCase { final Library libraryQ = libraryTable.createLibrary("Q"); assertEventsCount(0); - ModifiableRootModel[] rootModels = new ModifiableRootModel[]{rootModelA, rootModelB}; + ModifiableRootModel[] rootModels = {rootModelA, rootModelB}; if (rootModels.length > 0) { ModifiableModelCommitter.multiCommit(rootModels, ModuleManager.getInstance(rootModels[0].getProject()).getModifiableModel()); } @@ -337,8 +337,8 @@ public class RootsChangedTest extends ModuleTestCase { } private static class MyModuleRootListener implements ModuleRootListener { - private int beforeCount = 0; - private int afterCount = 0; + private int beforeCount; + private int afterCount; @Override public void beforeRootsChange(ModuleRootEvent event) { diff --git a/platform/analysis-api/src/com/intellij/codeInspection/SuppressIntentionAction.java b/platform/analysis-api/src/com/intellij/codeInspection/SuppressIntentionAction.java index 369dd223eab9..6835134ca375 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/SuppressIntentionAction.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/SuppressIntentionAction.java @@ -73,7 +73,6 @@ public abstract class SuppressIntentionAction implements Iconable, IntentionActi * @param project the project in which the file is opened. * @param editor the editor for the file. * @param element the element under cursor. - * @throws IncorrectOperationException * */ public abstract void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException; diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java index 46bd56e55668..fc65b991cdc1 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java @@ -37,6 +37,8 @@ import java.net.URL; * Date: 9/28/11 */ public abstract class InspectionToolWrapper { + public static final InspectionToolWrapper[] EMPTY_ARRAY = new InspectionToolWrapper[0]; + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.InspectionToolWrapper"); protected T myTool; diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java b/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java index b727fe954f32..9bc6190b2bda 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java @@ -50,7 +50,8 @@ public class SuppressIntentionActionFromFix extends SuppressIntentionAction { @NotNull public static SuppressIntentionAction[] convertBatchToSuppressIntentionActions(@NotNull SuppressQuickFix[] actions) { - return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, fix -> convertBatchToSuppressIntentionAction(fix)); + return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, + SuppressIntentionActionFromFix::convertBatchToSuppressIntentionAction); } @Override @@ -93,6 +94,7 @@ public class SuppressIntentionActionFromFix extends SuppressIntentionAction { return myFix.getFamilyName(); } + @Override public boolean isSuppressAll() { return myFix.isSuppressAll(); } diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationContextImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationContextImpl.groovy index c02dfb7031e6..a201cc319c51 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationContextImpl.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationContextImpl.groovy @@ -165,6 +165,7 @@ class CompilationContextImpl implements CompilationContext { unpackCompiledClasses(messages, ant, classesOutput, options) outputDirectoriesToKeep.add(classesDirName) } + messages.info("Incremental compilation: " + options.incrementalCompilation) if (options.incrementalCompilation) { outputDirectoriesToKeep.add(dataDirName) outputDirectoriesToKeep.add(classesDirName) @@ -211,6 +212,7 @@ class CompilationContextImpl implements CompilationContext { messages.info("Skipped cleaning for $file.absolutePath") } else { + messages.info("Deleting $file.absolutePath") FileUtil.delete(file) } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemBeforeRunTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemBeforeRunTask.java index 2cf934cc24ad..69d757084e5f 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemBeforeRunTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemBeforeRunTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -44,7 +44,7 @@ public class ExternalSystemBeforeRunTask extends BeforeRunTask tasks = ContainerUtilRt.newArrayList(); @@ -106,9 +106,9 @@ public abstract class ExternalSystemBeforeRunTaskProvider extends BeforeRunTaskP @Override public boolean executeTask(DataContext context, - RunConfiguration configuration, - ExecutionEnvironment env, - ExternalSystemBeforeRunTask beforeRunTask) { + @NotNull RunConfiguration configuration, + @NotNull ExecutionEnvironment env, + @NotNull ExternalSystemBeforeRunTask beforeRunTask) { final ExternalSystemTaskExecutionSettings executionSettings = beforeRunTask.getTaskExecutionSettings(); diff --git a/platform/lang-api/src/com/intellij/execution/BeforeRunTask.java b/platform/lang-api/src/com/intellij/execution/BeforeRunTask.java index 08d3e4408c07..517741ed5483 100644 --- a/platform/lang-api/src/com/intellij/execution/BeforeRunTask.java +++ b/platform/lang-api/src/com/intellij/execution/BeforeRunTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -16,6 +16,7 @@ package com.intellij.execution; +import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.util.Key; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -27,6 +28,9 @@ import org.jetbrains.annotations.NotNull; public abstract class BeforeRunTask implements Cloneable { @NotNull protected final Key myProviderId; + + // cannot be set to true by default, because RunManager.getHardcodedBeforeRunTasks creates before run task for each provider + // and some providers set enabled to true in the constructor to indicate, that before run task should be added to RC by default (on create) private boolean myIsEnabled; protected BeforeRunTask(@NotNull Key providerId) { @@ -46,18 +50,27 @@ public abstract class BeforeRunTask implements Cloneabl myIsEnabled = isEnabled; } - public void writeExternal(Element element) { - element.setAttribute("enabled", String.valueOf(myIsEnabled)); + /** + * @deprecated Use PersistentStateComponent (see LaunchBrowserBeforeRunTask for example). + */ + public void writeExternal(@NotNull Element element) { + if (this instanceof PersistentStateComponent) { + ((PersistentStateComponent)this).getState(); + } + else { + element.setAttribute("enabled", String.valueOf(myIsEnabled)); + } } - public void readExternal(Element element) { + /** + * @deprecated Use PersistentStateComponent (see LaunchBrowserBeforeRunTask for example). + */ + public void readExternal(@NotNull Element element) { String attribValue = element.getAttributeValue("enabled"); if (attribValue == null) { attribValue = element.getAttributeValue("value"); // maintain compatibility with old format } - if (attribValue == null) - attribValue = "true"; - myIsEnabled = Boolean.valueOf(attribValue).booleanValue(); + myIsEnabled = attribValue == null || Boolean.parseBoolean(attribValue); } //Task may aggregate several items or targets to do (e.g. BuildArtifactsBeforeRunTask) diff --git a/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java b/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java index 96fce915bd9b..9533361c69cc 100644 --- a/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java +++ b/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java @@ -41,15 +41,18 @@ public abstract class BeforeRunTaskProvider { return null; } - public abstract String getDescription(T task); - + public String getDescription(T task) { + return getName(); + } @Nullable public Icon getTaskIcon(T task) { return null; } - public abstract boolean isConfigurable(); + public boolean isConfigurable() { + return false; + } /** * @return 'before run' task for the configuration or null, if the task from this provider is not applicable to the specified configuration @@ -60,11 +63,15 @@ public abstract class BeforeRunTaskProvider { /** * @return {@code true} if task configuration is changed */ - public abstract boolean configureTask(final RunConfiguration runConfiguration, T task); + public boolean configureTask(@NotNull RunConfiguration runConfiguration, @NotNull T task) { + return false; + } - public abstract boolean canExecuteTask(RunConfiguration configuration, T task); + public boolean canExecuteTask(@NotNull RunConfiguration configuration, @NotNull T task) { + return true; + } - public abstract boolean executeTask(DataContext context, RunConfiguration configuration, ExecutionEnvironment env, T task); + public abstract boolean executeTask(DataContext context, @NotNull RunConfiguration configuration, @NotNull ExecutionEnvironment env, @NotNull T task); /** * diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index df91737f02f5..f98e1bb2a830 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -250,6 +250,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr @Override public void setDocument(Document doc) { super.setDocument(doc); + doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE); if (doc instanceof StyledDocument) { doc.putProperty("imageCache", myImageProvider); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/GotoInspectionModel.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/GotoInspectionModel.java index e02c51a9a7a4..8c6f7de850ab 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/GotoInspectionModel.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/GotoInspectionModel.java @@ -35,7 +35,6 @@ import java.util.Map; * @author Konstantin Bulenkov */ public class GotoInspectionModel extends SimpleChooseByNameModel { - private static final InspectionToolWrapper[] EMPTY_WRAPPERS_ARRAY = new InspectionToolWrapper[0]; private final Map myToolNames = new HashMap<>(); private final String[] myNames; private final InspectionListCellRenderer myListCellRenderer = new InspectionListCellRenderer(); @@ -69,7 +68,7 @@ public class GotoInspectionModel extends SimpleChooseByNameModel { public Object[] getElementsByName(final String name, final String pattern) { final InspectionToolWrapper tool = myToolNames.get(name); if (tool == null) { - return EMPTY_WRAPPERS_ARRAY; + return InspectionToolWrapper.EMPTY_ARRAY; } return new InspectionToolWrapper[] {tool}; } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java index cf96838fdd13..bb0ebe034bbe 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java @@ -125,7 +125,7 @@ extends BeforeRunTaskProvider) { + if (!task.isEnabled) { + child.setAttribute("enabled", "false") + } + task.serializeStateInto(child) + } + else { + task.writeExternal(child) + } methodElement.addContent(child) } return methodElement @@ -800,7 +806,14 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi val key = methodElement.getAttributeValue(NAME_ATTR) val provider = stringIdToBeforeRunProvider.getOrPut(key) { UnknownBeforeRunTaskProvider(key) } val beforeRunTask = (if (provider is RunConfigurationBeforeRunProvider) provider.createTask(settings.configuration, this) else provider.createTask(settings.configuration)) ?: continue - beforeRunTask.readExternal(methodElement) + if (beforeRunTask is PersistentStateComponent<*>) { + // for PersistentStateComponent we don't write default value for enabled, so, set it to true explicitly + beforeRunTask.isEnabled = true + beforeRunTask.deserializeAndLoadState(methodElement) + } + else { + beforeRunTask.readExternal(methodElement) + } if (result == null) { result = SmartList() } @@ -996,8 +1009,8 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi private fun getHardcodedBeforeRunTasks(configuration: RunConfiguration): List> { var result: MutableList>? = null for (provider in Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, project)) { - val task = provider.createTask(configuration) - if (task != null && task.isEnabled) { + val task = provider.createTask(configuration) ?: continue + if (task.isEnabled) { configuration.factory.configureBeforeRunTaskDefaults(provider.id, task) if (task.isEnabled) { if (result == null) { diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.kt b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.kt index 353718bb4828..1e7ed9860a92 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.kt +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.kt @@ -17,7 +17,7 @@ package com.intellij.execution.impl import com.intellij.configurationStore.SerializableScheme import com.intellij.configurationStore.deserializeAndLoadState -import com.intellij.configurationStore.serializeInto +import com.intellij.configurationStore.serializeStateInto import com.intellij.execution.* import com.intellij.execution.configurations.* import com.intellij.execution.runners.ProgramRunner @@ -282,7 +282,7 @@ class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(private val m private fun serializeConfigurationInto(configuration: RunConfiguration, element: Element) { if (configuration is PersistentStateComponent<*>) { - configuration.state!!.serializeInto(element) + configuration.serializeStateInto(element) } else { configuration.writeExternal(element) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/UnknownBeforeRunTaskProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/UnknownBeforeRunTaskProvider.java index 481649256f0f..9928cd681e96 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/UnknownBeforeRunTaskProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/UnknownBeforeRunTaskProvider.java @@ -57,25 +57,20 @@ public class UnknownBeforeRunTaskProvider extends BeforeRunTaskProvider { +public class PersistableCodeStyleSchemes extends CodeStyleSchemesImpl implements PersistentStateComponent { public String CURRENT_SCHEME_NAME = CodeStyleSchemeImpl.DEFAULT_SCHEME_NAME; public PersistableCodeStyleSchemes(@NotNull SchemeManagerFactory schemeManagerFactory) { @@ -65,6 +65,7 @@ class PersistableCodeStyleSchemes extends CodeStyleSchemesImpl implements Persis @Override public void loadState(Element state) { + CURRENT_SCHEME_NAME = CodeStyleSchemeImpl.DEFAULT_SCHEME_NAME; XmlSerializer.deserializeInto(this, state); CodeStyleScheme current = CURRENT_SCHEME_NAME == null ? null : mySchemeManager.findSchemeByName(CURRENT_SCHEME_NAME); setCurrentScheme(current == null ? getDefaultScheme() : current); diff --git a/platform/lang-impl/src/com/intellij/tools/AbstractToolBeforeRunTask.java b/platform/lang-impl/src/com/intellij/tools/AbstractToolBeforeRunTask.java index a5cc185fa125..7953ed78ed0f 100644 --- a/platform/lang-impl/src/com/intellij/tools/AbstractToolBeforeRunTask.java +++ b/platform/lang-impl/src/com/intellij/tools/AbstractToolBeforeRunTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -51,7 +51,7 @@ public abstract class AbstractToolBeforeRunTask? = null, } if (growPolicy == GrowPolicy.SHORT_TEXT) { -// cc().minWidth("210") cc().maxWidth("210") } + else if (growPolicy == GrowPolicy.MEDIUM_TEXT) { + cc().minWidth("210") + cc().maxWidth("350") + } return _cc } diff --git a/platform/platform-impl/src/com/intellij/ui/layout/Row.kt b/platform/platform-impl/src/com/intellij/ui/layout/Row.kt index 75bf50abfad7..ff0e1998aa04 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/Row.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/Row.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -148,5 +148,5 @@ abstract class Row() { } enum class GrowPolicy { - SHORT_TEXT + SHORT_TEXT, MEDIUM_TEXT } \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index dca03e9be781..9647a5d61a6b 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -585,6 +585,8 @@ key="browsers.settings" bundle="messages.IdeBundle"/> + + diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/DefaultStateSerializer.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/DefaultStateSerializer.kt index e079a67292d1..a3f6dde6e3a1 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/DefaultStateSerializer.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/DefaultStateSerializer.kt @@ -30,7 +30,7 @@ fun deserializeState(stateElement: Element?, stateClass: Class, mergeInto stateClass == Element::class.java -> stateElement as T? JDOMExternalizable::class.java.isAssignableFrom(stateClass) -> { if (mergeInto != null) { - LOG.error("State is ${stateClass.name}, merge into is ${mergeInto.toString()}, state element text is ${JDOMUtil.writeElement(stateElement)}") + LOG.error("State is ${stateClass.name}, merge into is $mergeInto, state element text is ${JDOMUtil.writeElement(stateElement)}") } val t = ReflectionUtil.newInstance(stateClass) diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/xmlSerializer.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/xmlSerializer.kt index 6651be07dec2..2cfc6b6e074e 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/xmlSerializer.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/xmlSerializer.kt @@ -119,15 +119,24 @@ fun PersistentStateComponent<*>.deserializeAndLoadState(element: Element) { (this as PersistentStateComponent).loadState(state) } +fun PersistentStateComponent<*>.serializeStateInto(element: Element) { + state?.let { serializeObjectInto(it, element) } +} + +@Deprecated("") fun T.serializeInto(target: Element) { - if (this is Element) { - val iterator = children.iterator() + serializeObjectInto(this, target) +} + +fun serializeObjectInto(o: Any, target: Element) { + if (o is Element) { + val iterator = o.children.iterator() for (child in iterator) { iterator.remove() target.addContent(child) } - val attributeIterator = attributes.iterator() + val attributeIterator = o.attributes.iterator() for (attribute in attributeIterator) { attributeIterator.remove() target.setAttribute(attribute) @@ -135,8 +144,8 @@ fun T.serializeInto(target: Element) { return } - val binding = serializer.getClassBinding(javaClass) - (binding as BeanBinding).serializeInto(this, target, null) + val binding = serializer.getClassBinding(o.javaClass) + (binding as BeanBinding).serializeInto(o, target, getDefaultSerializationFilter()) } private val serializer = object : XmlSerializerImpl.XmlSerializerBase() { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java index 0710feaa8309..65c9bf372724 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java @@ -455,7 +455,7 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel for (ModuleExtension extension : myExtensions) { if (extension instanceof PersistentStateComponent) { //noinspection ConstantConditions - XmlSerializer.serializeInto(((PersistentStateComponent)extension).getState(), element); + XmlSerializer.serializeStateInto(((PersistentStateComponent)extension), element); } else { //noinspection deprecation diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java index 986ed1c2fa10..6a6e8f3a5cbb 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java @@ -53,7 +53,8 @@ public class ServerTaskExecutorImpl implements ServerTaskExecutor { } catch (Throwable e) { LOG.info(e); - callback.errorOccurred(e.getMessage()); + String message = e.getMessage(); + callback.errorOccurred(message != null ? message : e.getClass().getName()); } }); } diff --git a/platform/testFramework/src/com/intellij/mock/MockInspectionProfile.java b/platform/testFramework/src/com/intellij/mock/MockInspectionProfile.java index 1b5753f3acf0..fbbe38ef0fb1 100644 --- a/platform/testFramework/src/com/intellij/mock/MockInspectionProfile.java +++ b/platform/testFramework/src/com/intellij/mock/MockInspectionProfile.java @@ -29,7 +29,7 @@ import java.util.Set; * @author peter */ public class MockInspectionProfile extends InspectionProfileImpl { - private InspectionToolWrapper[] myInspectionTools = new InspectionToolWrapper[0]; + private InspectionToolWrapper[] myInspectionTools = InspectionToolWrapper.EMPTY_ARRAY; private final Set myDisabledTools = new THashSet<>(); public MockInspectionProfile() { diff --git a/platform/testFramework/src/com/intellij/testFramework/FixtureRule.kt b/platform/testFramework/src/com/intellij/testFramework/FixtureRule.kt index d5412608c8d9..e2f4581ec6e9 100644 --- a/platform/testFramework/src/com/intellij/testFramework/FixtureRule.kt +++ b/platform/testFramework/src/com/intellij/testFramework/FixtureRule.kt @@ -30,7 +30,6 @@ import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.project.ex.ProjectEx import com.intellij.openapi.project.ex.ProjectManagerEx import com.intellij.openapi.project.impl.ProjectManagerImpl -import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS @@ -101,6 +100,7 @@ class ProjectRule(val projectDescriptor: LightProjectDescriptor = LightProjectDe sharedProject = null sharedModule = null (ProjectManager.getInstance() as ProjectManagerImpl).forceCloseProject(project, true) + (VirtualFilePointerManager.getInstance() as VirtualFilePointerManagerImpl).assertPointersAreDisposed() } } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestBase.java b/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestBase.java index 7d334c5075f1..e140ed7c0b78 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestBase.java +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestBase.java @@ -77,7 +77,7 @@ import static org.junit.Assert.*; @RunWith(GuiTestLocalRunner.class) public abstract class GuiTestBase { - protected Robot myRobot; + public Robot myRobot; private final Logger LOG = Logger.getInstance(GuiTestBase.class); diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestLocalRunner.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestLocalRunner.kt index 1256de53acaa..34b3c118e79e 100755 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestLocalRunner.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestLocalRunner.kt @@ -38,7 +38,9 @@ import kotlin.reflect.KClass class GuiTestLocalRunner @Throws(InitializationError::class) -constructor(testClass: Class<*>) : BlockJUnit4ClassRunner(testClass) { + constructor(testClass: Class<*>, val ide: Ide?) : BlockJUnit4ClassRunner(testClass) { + + constructor(testClass: Class<*>): this(testClass, null) val SERVER_LOG = org.apache.log4j.Logger.getLogger("#com.intellij.testGuiFramework.framework.GuiTestLocalRunner")!! val criticalError = Ref(false) @@ -67,8 +69,10 @@ constructor(testClass: Class<*>) : BlockJUnit4ClassRunner(testClass) { val server = JUnitServerHolder.getServer() try { - if (!server.isConnected()) - runIdeLocally(port = server.getPort(), ide = getIdeFromAnnotation(this@GuiTestLocalRunner.testClass.javaClass)) + if (!server.isConnected()) { + val localIde = ide ?: getIdeFromAnnotation(this@GuiTestLocalRunner.testClass.javaClass) + runIdeLocally(port = server.getPort(), ide = localIde) + } val jUnitTestContainer = JUnitTestContainer(method.declaringClass, method.name) server.send(TransportMessage(MessageType.RUN_TEST, jUnitTestContainer)) } @@ -147,7 +151,5 @@ constructor(testClass: Class<*>) : BlockJUnit4ClassRunner(testClass) { return Ide(ideType, 0, 0) } } - - } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestSuite.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestSuite.kt index 614507555e8b..ec90f2ee64d9 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestSuite.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/framework/GuiTestSuite.kt @@ -40,9 +40,7 @@ class GuiTestSuite(suiteClass: Class<*>, val builder: RunnerBuilder) : Suite(sui //let's start IDE to complete installation, import configs and etc before running tests if (myFirstStart) firstStart() val testClass = runner.description.testClass - //check that ide types are equal - check(GuiTestLocalRunner.getIdeFromAnnotation(testClass).ideType.javaClass == myIde.ideType.javaClass) - val guiTestLocalRunner = GuiTestLocalRunner(testClass) + val guiTestLocalRunner = GuiTestLocalRunner(testClass, myIde) super.runChild(guiTestLocalRunner, notifier) } catch (e: Exception) { @@ -59,5 +57,4 @@ class GuiTestSuite(suiteClass: Class<*>, val builder: RunnerBuilder) : Suite(sui } - } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt index 2466dd354630..985be993d9ac 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt @@ -122,7 +122,6 @@ open class GuiTestCase : GuiTestBase() { val screenshotTaker = ScreenshotTaker() var pathToSaveScreenshots = getTestScreenshotDirPath() - val settingsTitle: String = if (isMac()) "Preferences" else "Settings" val defaultSettingsTitle: String = if (isMac()) "Default Preferences" else "Default Settings" val slash: String = File.separator @@ -137,6 +136,7 @@ open class GuiTestCase : GuiTestBase() { @Throws(InvocationTargetException::class, InterruptedException::class) override fun tearDown() { + closeAllProjects() super.tearDown() } @@ -713,10 +713,10 @@ open class GuiTestCase : GuiTestBase() { return "@${uiScaleVal}x" } - protected fun waitUntilFound(container: Container?, - componentClass: Class, - timeout: Long, - matcher: (ComponentType) -> Boolean): ComponentType { + fun waitUntilFound(container: Container?, + componentClass: Class, + timeout: Long, + matcher: (ComponentType) -> Boolean): ComponentType { return GuiTestUtil.waitUntilFound(myRobot, container, typeMatcher(componentClass) { matcher(it) }, timeout.toFestTimeout()) } @@ -745,5 +745,4 @@ open class GuiTestCase : GuiTestBase() { return flagCheckFunction() } } - } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestUtilKt.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestUtilKt.kt index e2a86dad5d28..818e741867cd 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestUtilKt.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestUtilKt.kt @@ -266,6 +266,19 @@ object GuiTestUtilKt { return result?.first } + fun ensureCreateHasDone(guiTestCase: GuiTestCase) { + try { + com.intellij.testGuiFramework.impl.GuiTestUtilKt.waitUntilGone(robot = guiTestCase.myRobot, + matcher = com.intellij.testGuiFramework.impl.GuiTestUtilKt.typeMatcher( + com.intellij.openapi.wm.impl.welcomeScreen.FlatWelcomeFrame::class.java) { it.isShowing }) + } + catch (timeoutError: WaitTimedOutError) { + with(guiTestCase) { + welcomeFrame { button("Create").clickWhenEnabled() } + } + } + } + } fun main(args: Array) { diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index b481623485bd..ad83b2b58a15 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -231,6 +231,7 @@ public class UsageViewImpl implements UsageView { return expandingAll ? EmptyEnumeration.getInstance() : super.getExpandedDescendants(parent); } }; + myTree.setName("UsageViewTree"); myRootPanel = new MyPanel(myTree); Disposer.register(this, myRootPanel); diff --git a/platform/util/src/com/intellij/util/io/zip/JBZipEntry.java b/platform/util/src/com/intellij/util/io/zip/JBZipEntry.java index 2c5945f60452..e7522da5c305 100644 --- a/platform/util/src/com/intellij/util/io/zip/JBZipEntry.java +++ b/platform/util/src/com/intellij/util/io/zip/JBZipEntry.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; @@ -370,9 +371,14 @@ public class JBZipEntry implements Cloneable { } private InputStream getInputStream() throws IOException { + myFile.ensureFlushed(getHeaderOffset() + JBZipFile.LFH_OFFSET_FOR_FILENAME_LENGTH + JBZipFile.WORD); long start = calcDataOffset(); - - BoundedInputStream bis = new BoundedInputStream(start, getCompressedSize()); + long size = getCompressedSize(); + myFile.ensureFlushed(start + size); + if (myFile.archive.length() < start + size) { + throw new EOFException(); + } + BoundedInputStream bis = new BoundedInputStream(start, size); switch (getMethod()) { case ZipEntry.STORED: return bis; diff --git a/platform/util/src/com/intellij/util/io/zip/JBZipFile.java b/platform/util/src/com/intellij/util/io/zip/JBZipFile.java index a8b5ce8969cd..08afcbd6ec3f 100644 --- a/platform/util/src/com/intellij/util/io/zip/JBZipFile.java +++ b/platform/util/src/com/intellij/util/io/zip/JBZipFile.java @@ -187,7 +187,7 @@ public class JBZipFile { } myOutputStream.finish(); - archive.setLength(myOutputStream.written); + archive.setLength(myOutputStream.getWritten()); } archive.close(); } @@ -454,4 +454,8 @@ public class JBZipFile { } return myOutputStream; } + + void ensureFlushed(long end) throws IOException { + if (myOutputStream != null) myOutputStream.ensureFlushed(end); + } } diff --git a/platform/util/src/com/intellij/util/io/zip/JBZipOutputStream.java b/platform/util/src/com/intellij/util/io/zip/JBZipOutputStream.java index df5276ab40de..1ad6920469cd 100644 --- a/platform/util/src/com/intellij/util/io/zip/JBZipOutputStream.java +++ b/platform/util/src/com/intellij/util/io/zip/JBZipOutputStream.java @@ -48,7 +48,7 @@ class JBZipOutputStream { private final CRC32 crc = new CRC32(); - long written = 0; + private long writtenOnDisk = 0; /** * The encoding to use for filenames and the file comment. @@ -93,8 +93,7 @@ class JBZipOutputStream { public JBZipOutputStream(JBZipFile file, long currentCDOffset) throws IOException { myFile = file; raf = myFile.archive; - written = currentCDOffset; - raf.seek(currentCDOffset); + writtenOnDisk = currentCDOffset; } /** @@ -129,12 +128,12 @@ class JBZipOutputStream { * @since 1.1 */ public void finish() throws IOException { - long cdOffset = written; + long cdOffset = getWritten(); final List entries = myFile.getEntries(); for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) { writeCentralFileHeader(entries.get(i)); } - long cdLength = written - cdOffset; + long cdLength = getWritten() - cdOffset; writeCentralDirectoryEnd(cdLength, cdOffset); flushBuffer(); def.end(); @@ -209,7 +208,7 @@ class JBZipOutputStream { * @since 1.1 */ protected void writeLocalFileHeader(JBZipEntry ze) throws IOException { - ze.setHeaderOffset(written); + ze.setHeaderOffset(getWritten()); writeOut(LFH_SIG); @@ -376,11 +375,16 @@ class JBZipOutputStream { if (myBuffer.size() > 8192) { flushBuffer(); } - written += length; + } + + void ensureFlushed(long end) throws IOException { + if (end > writtenOnDisk) flushBuffer(); } private void flushBuffer() throws IOException { + raf.seek(writtenOnDisk); raf.write(myBuffer.getInternalBuffer(), 0, myBuffer.size()); + writtenOnDisk += myBuffer.size(); myBuffer.reset(); } @@ -423,4 +427,8 @@ class JBZipOutputStream { writeLocalFileHeader(entry); writeOut(outputBytes, 0, outputBytesLength); } + + long getWritten() { + return writtenOnDisk + myBuffer.size(); + } } diff --git a/platform/util/testSrc/com/intellij/util/io/zip/UpdateableZipTest.java b/platform/util/testSrc/com/intellij/util/io/zip/UpdateableZipTest.java index b2dfb56e36f0..5cac1f2292af 100644 --- a/platform/util/testSrc/com/intellij/util/io/zip/UpdateableZipTest.java +++ b/platform/util/testSrc/com/intellij/util/io/zip/UpdateableZipTest.java @@ -20,6 +20,7 @@ package com.intellij.util.io.zip; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.CharsetToolkit; import junit.framework.TestCase; import java.io.*; @@ -108,6 +109,64 @@ public class UpdateableZipTest extends TestCase { utilZip.close(); } + public void testReadWrite1() throws Exception { + JBZipFile jbZip = new JBZipFile(zipFile); + try { + assertEntryWithContentExists(jbZip, "/first", "first"); + assertEntryWithContentExists(jbZip, "/second", "second"); + + createOrReplaceEntryData(jbZip, "/third", "third"); + + assertEntryWithContentExists(jbZip, "/third", "third"); + } + finally { + jbZip.close(); + } + } + + public void testReadWrite2() throws Exception { + JBZipFile jbZip = new JBZipFile(zipFile); + try { + assertEntryWithContentExists(jbZip, "/first", "first"); + assertEntryWithContentExists(jbZip, "/second", "second"); + + createOrReplaceEntryData(jbZip, "/first", "first_new"); + + assertEntryWithContentExists(jbZip, "/first", "first_new"); + } + finally { + jbZip.close(); + } + } + + public void testMissingSeeks() throws Exception { + JBZipFile jbZip = new JBZipFile(zipFile); + try { + assertEntryWithContentExists(jbZip, "/first", "first"); + assertEntryWithContentExists(jbZip, "/second", "second"); + + //seek end + createOrReplaceEntryData(jbZip, "/third", "third"); + //seek somewhere + assertEntryWithContentExists(jbZip, "/first", "first"); + //write somewhere :) + createOrReplaceEntryData(jbZip, "/forth", "forth"); + + assertEntryWithContentExists(jbZip, "/first", "first"); + assertEntryWithContentExists(jbZip, "/second", "second"); + assertEntryWithContentExists(jbZip, "/third", "third"); + assertEntryWithContentExists(jbZip, "/forth", "forth"); + } + finally { + jbZip.close(); + } + } + + private void createOrReplaceEntryData(JBZipFile jbZip, String name, String data) throws IOException { + JBZipEntry newEntry = jbZip.getOrCreateEntry(name); + newEntry.setData(data.getBytes(CharsetToolkit.UTF8_CHARSET)); + } + /* public void testAppendToIdeaJar() throws Exception { //ProfilingUtil.startCPUProfiling(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index f7f8f527be6e..18dc8626aa73 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -335,9 +335,11 @@ public class XDebuggerManagerImpl extends XDebuggerManager } @Override - public void loadState(final XDebuggerState state) { - myBreakpointManager.loadState(state.myBreakpointManagerState); - myWatchesManager.loadState(state.myWatchesManagerState); + public void loadState(@NotNull XDebuggerState state) { + XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState = state.myBreakpointManagerState; + myBreakpointManager.loadState(breakpointManagerState == null ? new XBreakpointManagerImpl.BreakpointManagerState() : breakpointManagerState); + XDebuggerWatchesManager.WatchesManagerState managerState = state.myWatchesManagerState; + myWatchesManager.loadState(managerState == null ? new XDebuggerWatchesManager.WatchesManagerState() : managerState); } public void showExecutionPosition() { @@ -346,32 +348,36 @@ public class XDebuggerManagerImpl extends XDebuggerManager @SuppressWarnings("UnusedDeclaration") public static class XDebuggerState { + @Nullable private XBreakpointManagerImpl.BreakpointManagerState myBreakpointManagerState; + @Nullable private XDebuggerWatchesManager.WatchesManagerState myWatchesManagerState; public XDebuggerState() { } - public XDebuggerState(final XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState, XDebuggerWatchesManager.WatchesManagerState watchesManagerState) { + public XDebuggerState(@Nullable XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState, @Nullable XDebuggerWatchesManager.WatchesManagerState watchesManagerState) { myBreakpointManagerState = breakpointManagerState; myWatchesManagerState = watchesManagerState; } + @Nullable @Property(surroundWithTag = false) public XBreakpointManagerImpl.BreakpointManagerState getBreakpointManagerState() { return myBreakpointManagerState; } - public void setBreakpointManagerState(final XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState) { + public void setBreakpointManagerState(@Nullable final XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState) { myBreakpointManagerState = breakpointManagerState; } + @Nullable @Property(surroundWithTag = false) public XDebuggerWatchesManager.WatchesManagerState getWatchesManagerState() { return myWatchesManagerState; } - public void setWatchesManagerState(XDebuggerWatchesManager.WatchesManagerState watchesManagerState) { + public void setWatchesManagerState(@Nullable XDebuggerWatchesManager.WatchesManagerState watchesManagerState) { myWatchesManagerState = watchesManagerState; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java index 2b0e172c3872..699f5b284f83 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java @@ -387,7 +387,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta } @Override - public void loadState(final BreakpointManagerState state) { + public void loadState(@NotNull BreakpointManagerState state) { myBreakpointsDialogSettings = state.getBreakpointsDialogProperties(); myAllBreakpoints.clear(); diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTask.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTask.java index 9612ca7417f2..21e09f677b17 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTask.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -21,6 +21,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; /** * @author Eugene Zhuravlev @@ -50,7 +51,7 @@ public class AntBeforeRunTask extends BeforeRunTask{ myTargetName = targetName; } - public void writeExternal(Element element) { + public void writeExternal(@NotNull Element element) { super.writeExternal(element); if (myAntFileUrl != null && myTargetName != null) { element.setAttribute("antfile", myAntFileUrl); @@ -58,7 +59,7 @@ public class AntBeforeRunTask extends BeforeRunTask{ } } - public void readExternal(Element element) { + public void readExternal(@NotNull Element element) { super.readExternal(element); final String url = element.getAttributeValue("antfile"); final String targetName = element.getAttributeValue("target"); diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTaskProvider.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTaskProvider.java index b36fb06ebbf7..fd359e772c64 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTaskProvider.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBeforeRunTaskProvider.java @@ -74,7 +74,7 @@ public class AntBeforeRunTaskProvider extends BeforeRunTaskProvider { @@ -50,14 +51,14 @@ public class MavenBeforeRunTask extends BeforeRunTask { } @Override - public void writeExternal(Element element) { + public void writeExternal(@NotNull Element element) { super.writeExternal(element); if (myProjectPath != null) element.setAttribute("file", myProjectPath); if (myGoal != null) element.setAttribute("goal", myGoal); } @Override - public void readExternal(Element element) { + public void readExternal(@NotNull Element element) { super.readExternal(element); myProjectPath = element.getAttributeValue("file"); myGoal = element.getAttributeValue("goal"); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java index cb3c5fa5a0c5..280895a575e3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java @@ -105,7 +105,7 @@ public class MavenBeforeRunTasksProvider extends BeforeRunTaskProvider() { + @NotNull + @Override + public Result compute() { + return Result.create(computeBaseName(), file); + } - if (!StringUtil.containsChar(name, '_')) { - return FileUtil.getNameWithoutExtension(name); - } + private String computeBaseName() { + final String name = file.getName(); - final Matcher matcher = LOCALE_PATTERN.matcher(name); - final String baseNameWithExtension; - - int matchIndex = 0; - while (matcher.find(matchIndex)) { - final MatchResult matchResult = matcher.toMatchResult(); - final String[] splitted = matchResult.group(1).split("_"); - if (splitted.length > 1) { - final String langCode = splitted[1]; - if (!LOCALES_LANGUAGE_CODES.getValue().contains(langCode)) { - matchIndex = matchResult.start(1) + 1; - continue; + if (!StringUtil.containsChar(name, '_')) { + return FileUtil.getNameWithoutExtension(name); } - baseNameWithExtension = name.substring(0, matchResult.start(1)) + name.substring(matchResult.end(1)); + + final Matcher matcher = LOCALE_PATTERN.matcher(name); + final String baseNameWithExtension; + + int matchIndex = 0; + while (matcher.find(matchIndex)) { + final MatchResult matchResult = matcher.toMatchResult(); + final String[] splitted = matchResult.group(1).split("_"); + if (splitted.length > 1) { + final String langCode = splitted[1]; + if (!LOCALES_LANGUAGE_CODES.getValue().contains(langCode)) { + matchIndex = matchResult.start(1) + 1; + continue; + } + baseNameWithExtension = name.substring(0, matchResult.start(1)) + name.substring(matchResult.end(1)); + return FileUtil.getNameWithoutExtension(baseNameWithExtension); + } + } + baseNameWithExtension = name; return FileUtil.getNameWithoutExtension(baseNameWithExtension); } - } - baseNameWithExtension = name; - return FileUtil.getNameWithoutExtension(baseNameWithExtension); + }); } @NotNull diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index 40b5fc240e40..50397814c48d 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -197,17 +197,13 @@ public class ResourceBundleManager implements PersistentStateComponent 1) { if (isImpliedAttribute(attributeName)) { - defaultAttribute.setName(attributeName.substring(1)); + defaultAttribute = (XmlAttribute)defaultAttribute.setName(attributeName.substring(1)); } final String oldValue = defaultAttribute.getValue(); if (oldValue != null && StringUtil.containsChar(oldValue, '|')) { diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java b/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java index 2cf442638f0f..97ca78058f89 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.ide.browsers; import com.google.common.net.HostAndPort; @@ -50,7 +65,7 @@ public class BrowserStarter { } else { // we can't check page availability gracefully, so we just open it after some delay - openPageLater(1000); + openPageLater(); } } @@ -95,8 +110,8 @@ public class BrowserStarter { return 2000; } - private void openPageLater(int millis) { - JobScheduler.getScheduler().schedule(() -> openPageNow(), millis, TimeUnit.MILLISECONDS); + private void openPageLater() { + JobScheduler.getScheduler().schedule(() -> openPageNow(), 1000, TimeUnit.MILLISECONDS); } private void openPageNow() { diff --git a/xml/impl/src/com/intellij/ide/browsers/LaunchBrowserBeforeRunTaskProvider.kt b/xml/impl/src/com/intellij/ide/browsers/LaunchBrowserBeforeRunTaskProvider.kt new file mode 100644 index 000000000000..301cc0658d7c --- /dev/null +++ b/xml/impl/src/com/intellij/ide/browsers/LaunchBrowserBeforeRunTaskProvider.kt @@ -0,0 +1,144 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.browsers + +import com.intellij.execution.BeforeRunTask +import com.intellij.execution.BeforeRunTaskProvider +import com.intellij.execution.ExecutionListener +import com.intellij.execution.ExecutionManager +import com.intellij.execution.configurations.RunConfiguration +import com.intellij.execution.process.ProcessHandler +import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.icons.AllIcons +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.components.BaseState +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.ui.TextFieldWithBrowseButton +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.Key +import com.intellij.ui.components.CheckBox +import com.intellij.ui.components.dialog +import com.intellij.ui.layout.* +import com.intellij.util.ui.UIUtil +import com.intellij.util.xmlb.annotations.Attribute +import com.intellij.xml.XmlBundle +import javax.swing.Icon +import javax.swing.border.EmptyBorder + +internal class LaunchBrowserBeforeRunTaskProvider : BeforeRunTaskProvider() { + companion object { + val ID = Key.create("LaunchBrowser.Before.Run") + } + + override fun getName() = "Launch Web Browser" + + override fun getId() = ID + + override fun getIcon(): Icon = AllIcons.Nodes.PpWeb + + override fun isConfigurable() = true + + override fun createTask(runConfiguration: RunConfiguration) = LaunchBrowserBeforeRunTask() + + override fun configureTask(runConfiguration: RunConfiguration, task: LaunchBrowserBeforeRunTask): Boolean { + val state = task.state + val modificationCount = state.modificationCount + + val browserSelector = BrowserSelector() + val browserComboBox = browserSelector.mainComponent + if (UIUtil.isUnderAquaLookAndFeel()) { + browserComboBox.border = EmptyBorder(3, 0, 0, 0) + } + state.browser?.let { + browserSelector.selected = it + } + + val url = TextFieldWithBrowseButton() + state.url?.let { + url.text = it + } + + StartBrowserPanel.setupUrlField(url, runConfiguration.project) + + val startJavaScriptDebuggerCheckBox = if (JavaScriptDebuggerStarter.Util.hasStarters()) CheckBox(XmlBundle.message("start.browser.with.js.debugger"), state.withDebugger) else null + + val panel = panel { + row("Browser:") { + browserComboBox() + startJavaScriptDebuggerCheckBox?.invoke() + } + row("Url:") { + url(growPolicy = GrowPolicy.MEDIUM_TEXT) + } + } + dialog("Launch Web Browser", panel = panel, resizable = true, focusedComponent = url) + .show() + + state.browser = browserSelector.selected + state.url = url.text + if (startJavaScriptDebuggerCheckBox != null) { + state.withDebugger = startJavaScriptDebuggerCheckBox.isSelected + } + return modificationCount != state.modificationCount + } + + override fun executeTask(context: DataContext?, configuration: RunConfiguration, env: ExecutionEnvironment, task: LaunchBrowserBeforeRunTask): Boolean { + val disposable = Disposer.newDisposable() + Disposer.register(env.project, disposable) + val executionId = env.executionId + env.project.messageBus.connect(disposable).subscribe(ExecutionManager.EXECUTION_TOPIC, object: ExecutionListener { + override fun processNotStarted(executorId: String, env: ExecutionEnvironment) { + Disposer.dispose(disposable) + } + + override fun processStarted(executorId: String, env: ExecutionEnvironment, handler: ProcessHandler) { + if (env.executionId != executionId) { + return + } + + Disposer.dispose(disposable) + + val settings = StartBrowserSettings() + settings.browser = task.state.browser + settings.isStartJavaScriptDebugger = task.state.withDebugger + settings.url = task.state.url + settings.isSelected = true + BrowserStarter(configuration, settings, handler).start() + } + }) + return true + } +} + +internal class LaunchBrowserBeforeRunTaskState : BaseState() { + @get:Attribute(value = "browser", converter = WebBrowserReferenceConverter::class) + var browser by storedProperty() + @get:Attribute() + var url by string() + @get:Attribute() + var withDebugger by storedProperty(false) +} + +internal class LaunchBrowserBeforeRunTask : BeforeRunTask(LaunchBrowserBeforeRunTaskProvider.ID), PersistentStateComponent { + private var state = LaunchBrowserBeforeRunTaskState() + + override fun loadState(state: LaunchBrowserBeforeRunTaskState) { + state.resetModificationCount() + this.state = state + } + + override fun getState() = state +} \ No newline at end of file diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java index 99d0c633d8ee..8250d28b288d 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java @@ -16,7 +16,9 @@ package com.intellij.psi.impl.source.xml; import com.intellij.lang.ASTNode; +import com.intellij.lang.html.HTMLLanguage; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.pom.PomManager; import com.intellij.pom.PomModel; @@ -34,6 +36,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.xml.*; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; import com.intellij.xml.XmlAttributeDescriptor; import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.util.XmlUtil; @@ -310,11 +313,12 @@ public class XmlAttributeImpl extends XmlElementImpl implements XmlAttribute, Hi public PsiElement setName(@NotNull final String nameText) throws IncorrectOperationException { final ASTNode name = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(this); final String oldName = name.getText(); - final String oldValue = getValue(); + final String oldValue = ObjectUtils.notNull(getValue(), ""); final PomModel model = PomManager.getModel(getProject()); final XmlAttribute attribute = XmlElementFactory.getInstance(getProject()).createAttribute(nameText, oldValue, this); final ASTNode newName = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild((ASTNode)attribute); final XmlAspect aspect = model.getModelAspect(XmlAspect.class); + final Ref replaced = Ref.create(this); model.runTransaction(new PomTransactionBase(getParent(), aspect) { @Override public PomModelEvent runInner() { @@ -324,15 +328,17 @@ public class XmlAttributeImpl extends XmlElementImpl implements XmlAttribute, Hi xmlAspectChangeSet.add(new XmlAttributeSetImpl(getParent(), oldName, null)); xmlAspectChangeSet.add(new XmlAttributeSetImpl(getParent(), nameText, oldValue)); event.registerChangeSet(model.getModelAspect(XmlAspect.class), xmlAspectChangeSet); - if (oldValue.isEmpty()) { - CodeEditUtil.replaceChild(XmlAttributeImpl.this, name, newName); - } else { + if (!oldValue.isEmpty() && getLanguage().isKindOf(HTMLLanguage.INSTANCE)) { CodeEditUtil.replaceChild(getTreeParent(), XmlAttributeImpl.this, attribute.getNode()); + replaced.set(attribute); + } + else { + CodeEditUtil.replaceChild(XmlAttributeImpl.this, name, newName); } return event; } }); - return this; + return replaced.get(); } @Override