diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java index 24ed7b49b907..61e32f8aa50b 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java @@ -50,9 +50,9 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura myCbUseCompileServer.setVisible(ApplicationManager.getApplication().isInternal()); myPatternLegendLabel.setText("" + "Use ; to separate patterns and ! to negate a pattern.
" + - "Accepted wildcards: ? - exactly one symbol; * - zero or more symbols;
" + - "  / - path separator; /**/ - any number of directories;
" + - "  resources:* - for everything under a source root named resources" + + "Accepted wildcards: ? — exactly one symbol; * — zero or more symbols;
" + + "  / — path separator; /**/ — any number of directories;
" + + "  <dir_name>:<pattern> — restrict to source roots with the specified name" + ""); } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/SmartStepIntoActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java similarity index 50% rename from java/debugger/impl/src/com/intellij/debugger/actions/SmartStepIntoActionHandler.java rename to java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java index 3786d50a9f8c..294718ee7843 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/SmartStepIntoActionHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -15,75 +15,33 @@ */ package com.intellij.debugger.actions; -import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.SourcePosition; -import com.intellij.debugger.engine.RequestHint; -import com.intellij.debugger.engine.SuspendContextImpl; -import com.intellij.debugger.impl.DebuggerContextImpl; -import com.intellij.debugger.impl.DebuggerSession; -import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditor; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.TextEditor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.ui.awt.RelativePoint; import com.intellij.util.containers.OrderedSet; import com.intellij.util.text.CharArrayUtil; -import com.intellij.xdebugger.impl.actions.DebuggerActionHandler; -import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import gnu.trove.TObjectHashingStrategy; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; -public class SmartStepIntoActionHandler extends DebuggerActionHandler { - public void perform(@NotNull final Project project, final AnActionEvent event) { - final DebuggerContextImpl debuggerContext = (DebuggerManagerEx.getInstanceEx(project)).getContext(); - doStep(project, debuggerContext.getSourcePosition(), debuggerContext.getDebuggerSession()); +/** + * User: Alexander Podkhalyuzin + * Date: 22.11.11 + */ +public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { + @Override + public boolean isAvailable(final SourcePosition position) { + final PsiFile file = position.getFile(); + return file.getLanguage().isKindOf(JavaLanguage.INSTANCE); } - - private static void doStep(final @NotNull Project project, final @Nullable SourcePosition position, final @NotNull DebuggerSession session) { - final VirtualFile file = position != null ? position.getFile().getVirtualFile() : null; - final FileEditor fileEditor = file != null? FileEditorManager.getInstance(project).getSelectedEditor(file) : null; - if (fileEditor instanceof TextEditor) { - final List methods = findReferencedMethods(position); - if (methods.size() > 0) { - if (methods.size() == 1) { - session.stepInto(true, createSmartStepFilter(methods.get(0))); - } - else { - final PsiMethodListPopupStep popupStep = new PsiMethodListPopupStep(methods, new PsiMethodListPopupStep.OnChooseRunnable() { - public void execute(PsiMethod chosenMethod) { - session.stepInto(true, createSmartStepFilter(chosenMethod)); - } - }); - final ListPopup popup = JBPopupFactory.getInstance().createListPopup(popupStep); - final RelativePoint point = DebuggerUIUtil.calcPopupLocation(((TextEditor)fileEditor).getEditor(), position.getLine()); - popup.show(point); - } - return; - } - } - session.stepInto(true, null); - } - - @Nullable - private static RequestHint.SmartStepFilter createSmartStepFilter(final PsiMethod method) { - return new RequestHint.SmartStepFilter(method); - } - - - private static List findReferencedMethods(final SourcePosition position) { + @Override + public List findReferencedMethods(final SourcePosition position) { final int line = position.getLine(); if (line < 0) { return Collections.emptyList(); // the document has been changed @@ -95,8 +53,9 @@ public class SmartStepIntoActionHandler extends DebuggerActionHandler { // the file is not physical return Collections.emptyList(); } - + final Document doc = FileDocumentManager.getInstance().getDocument(vFile); + if (doc == null) return Collections.emptyList(); if (line >= doc.getLineCount()) { return Collections.emptyList(); // the document has been changed } @@ -144,13 +103,4 @@ public class SmartStepIntoActionHandler extends DebuggerActionHandler { } return Collections.emptyList(); } - - public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) { - final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext(); - DebuggerSession debuggerSession = context.getDebuggerSession(); - final boolean isPaused = debuggerSession != null && debuggerSession.isPaused(); - final SuspendContextImpl suspendContext = context.getSuspendContext(); - final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null; - return isPaused && hasCurrentThread; - } } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoActionHandler.java new file mode 100644 index 000000000000..512ab134c392 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoActionHandler.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2009 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.debugger.actions; + +import com.intellij.debugger.DebuggerManagerEx; +import com.intellij.debugger.SourcePosition; +import com.intellij.debugger.engine.RequestHint; +import com.intellij.debugger.engine.SuspendContextImpl; +import com.intellij.debugger.impl.DebuggerContextImpl; +import com.intellij.debugger.impl.DebuggerSession; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopup; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.containers.OrderedSet; +import com.intellij.util.text.CharArrayUtil; +import com.intellij.xdebugger.impl.actions.DebuggerActionHandler; +import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; +import gnu.trove.TObjectHashingStrategy; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +public class JvmSmartStepIntoActionHandler extends DebuggerActionHandler { + public void perform(@NotNull final Project project, final AnActionEvent event) { + final DebuggerContextImpl debuggerContext = (DebuggerManagerEx.getInstanceEx(project)).getContext(); + doStep(project, debuggerContext.getSourcePosition(), debuggerContext.getDebuggerSession()); + } + + private static void doStep(final @NotNull Project project, final @Nullable SourcePosition position, final @NotNull DebuggerSession session) { + final VirtualFile file = position != null ? position.getFile().getVirtualFile() : null; + final FileEditor fileEditor = file != null? FileEditorManager.getInstance(project).getSelectedEditor(file) : null; + if (fileEditor instanceof TextEditor) { + for (JvmSmartStepIntoHandler handler : Extensions.getExtensions(JvmSmartStepIntoHandler.EP_NAME)) { + if (handler.isAvailable(position) && handler.doSmartStep(position, session, (TextEditor)fileEditor)) return; + } + } + session.stepInto(true, null); + } + + public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) { + final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext(); + DebuggerSession debuggerSession = context.getDebuggerSession(); + final boolean isPaused = debuggerSession != null && debuggerSession.isPaused(); + final SuspendContextImpl suspendContext = context.getSuspendContext(); + final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null; + return isPaused && hasCurrentThread; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoHandler.java new file mode 100644 index 000000000000..d02029d7bf1b --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoHandler.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2011 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.debugger.actions; + +import com.intellij.debugger.SourcePosition; +import com.intellij.debugger.engine.RequestHint; +import com.intellij.debugger.impl.DebuggerSession; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopup; +import com.intellij.psi.PsiMethod; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * User: Alexander Podkhalyuzin + * Date: 22.11.11 + */ +public abstract class JvmSmartStepIntoHandler { + public static ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.debugger.jvmSmartStepIntoHandler"); + + public abstract List findReferencedMethods(SourcePosition position); + + public abstract boolean isAvailable(SourcePosition position); + + /** + * Override this if you haven't PsiMethod, like in Kotlin. + * @param position + * @param session + * @param fileEditor + * @return false to continue for another handler or for default action (step into) + */ + public boolean doSmartStep(SourcePosition position, final DebuggerSession session, TextEditor fileEditor) { + final List methods = findReferencedMethods(position); + if (methods.size() > 0) { + if (methods.size() == 1) { + session.stepInto(true, getSmartStepFilter(methods.get(0))); + } + else { + final PsiMethodListPopupStep popupStep = new PsiMethodListPopupStep(methods, new PsiMethodListPopupStep.OnChooseRunnable() { + public void execute(PsiMethod chosenMethod) { + session.stepInto(true, getSmartStepFilter(chosenMethod)); + } + }); + final ListPopup popup = JBPopupFactory.getInstance().createListPopup(popupStep); + final RelativePoint point = DebuggerUIUtil.calcPopupLocation(((TextEditor)fileEditor).getEditor(), position.getLine()); + popup.show(point); + } + return true; + } + return false; + } + + /** + * Override in case if your JVMNames slightly different then it can be provided by getJvmSignature method. + * @param method + * @return SmartStepFilter + */ + protected RequestHint.SmartStepFilter getSmartStepFilter(PsiMethod method) { + return new RequestHint.SmartStepFilter(method); + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index 0a8eaa55aa8b..3408858cec81 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -64,7 +64,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { private final QuickEvaluateActionHandler myQuickEvaluateHandler = new QuickEvaluateActionHandler(); private final JavaDebuggerSettingsPanelProvider myDebuggerSettingsPanelProvider = new JavaDebuggerSettingsPanelProvider(); private final MuteBreakpointsActionHandler myMuteBreakpointsHandler = new MuteBreakpointsActionHandler(); - private final DebuggerActionHandler mySmartStepIntoHandler = new SmartStepIntoActionHandler(); + private final DebuggerActionHandler mySmartStepIntoHandler = new JvmSmartStepIntoActionHandler(); private final DebuggerActionHandler myAddToWatchedActionHandler = new AddToWatchActionHandler(); private JavaMarkObjectActionHandler myMarkObjectActionHandler = new JavaMarkObjectActionHandler(); diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java b/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java index 1d6607a87cc3..d4cbf69d3191 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java @@ -140,7 +140,7 @@ public class RootsDetectionStep extends AbstractStepWithProgress selectedTypes = new HashSet(); for (DetectedRootData rootData : myDetectedRootsChooser.getMarkedElements()) { for (ProjectStructureDetector detector : rootData.getSelectedDetectors()) { - selectedTypes.add(detector.getClass().getName()); + selectedTypes.add(detector.getDetectorId()); } } mySequence.setTypes(selectedTypes); diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java index a1feb143647f..f4571186789c 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java @@ -68,7 +68,7 @@ public abstract class CreateFromSourcesMode extends WizardMode { sequence.addCommonStep(new RootsDetectionStep(projectBuilder, context, sequence, icon, "reference.dialogs.new.project.fromCode.source")); for (ProjectStructureDetector detector : ProjectStructureDetector.EP_NAME.getExtensions()) { for (ModuleWizardStep step : detector.createWizardSteps(projectBuilder, projectBuilder.getProjectDescriptor(detector), icon)) { - sequence.addSpecificStep(detector.getClass().getName(), step); + sequence.addSpecificStep(detector.getDetectorId(), step); } } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java index 8ce1f9c299fc..86786fa45d8b 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java @@ -52,6 +52,11 @@ public abstract class JavaSourceRootDetector extends ProjectStructureDetector { return DirectoryProcessingResult.PROCESS_CHILDREN; } + @Override + public String getDetectorId() { + return "Java"; + } + @NotNull protected abstract String getLanguageName(); diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectStructureDetector.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectStructureDetector.java index 636c791a6bef..71b53b25c185 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectStructureDetector.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectStructureDetector.java @@ -68,6 +68,10 @@ public abstract class ProjectStructureDetector { return Collections.emptyList(); } + public String getDetectorId() { + return getClass().getName(); + } + /** * Setup modules and libraries for the selected roots */ diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java index 17a1a42ccb02..2647a908975e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java @@ -19,7 +19,8 @@ import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypesProvider; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.diagnostic.LogMessageEx; +import com.intellij.diagnostic.errordialog.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -105,11 +106,8 @@ class JavaClassNameInsertHandler implements InsertHandler myRemotes; + private final Collection myBranchTrackInfos; - private GitConfig(Collection remotes) { + private GitConfig(Collection remotes, @NotNull Collection branchTrackInfos) { myRemotes = remotes; + myBranchTrackInfos = branchTrackInfos; } /** @@ -75,10 +79,19 @@ class GitConfig { *

* @return Git remotes defined in {@code .git/config}. */ + @NotNull Collection getRemotes() { return myRemotes; } + /** + * @return branch tracking information defined in {@code .git/config}. + */ + @NotNull + public Collection getBranchTrackInfos() { + return myBranchTrackInfos; + } + /** * Creates an instance of GitConfig by reading information from the specified {@code .git/config} file. * @param configFile @@ -102,6 +115,76 @@ class GitConfig { IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginManager.getPluginByClassName(GitConfig.class.getName())); ClassLoader classLoader = plugin == null ? null : plugin.getPluginClassLoader(); // null if IDEA is started from IDEA + Collection gitRemotes = parseRemotes(ini, classLoader); + Collection trackedInfos = parseTrackedInfos(ini, classLoader, gitRemotes); + + return new GitConfig(gitRemotes, trackedInfos); + } + + private static Collection parseTrackedInfos(Ini ini, ClassLoader classLoader, Collection remotes) { + Collection branchTrackInfos = new ArrayList(); + for (Map.Entry stringSectionEntry : ini.entrySet()) { + String sectionName = stringSectionEntry.getKey(); + Profile.Section section = stringSectionEntry.getValue(); + if (sectionName.startsWith("branch")) { + BranchConfig branchConfig = parseBranchSection(sectionName, section, classLoader); + GitBranchTrackInfo branchTrackInfo = convertBranchConfig(branchConfig, remotes); + if (branchTrackInfo != null) { + branchTrackInfos.add(branchTrackInfo); + } + } + } + return branchTrackInfos; + } + + @Nullable + private static GitBranchTrackInfo convertBranchConfig(@Nullable BranchConfig branchConfig, @NotNull Collection remotes) { + if (branchConfig == null) { + return null; + } + String branchName = branchConfig.getName(); + String remoteName = branchConfig.getBean().getRemote(); + String mergeName = branchConfig.getBean().getMerge(); + String rebaseName = branchConfig.getBean().getRebase(); + + if (StringUtil.isEmptyOrSpaces(mergeName) && StringUtil.isEmptyOrSpaces(rebaseName)) { + LOG.info("No branch." + branchName + ".merge/rebase item in the .git/config"); + return null; + } + if (StringUtil.isEmptyOrSpaces(remoteName)) { + LOG.info("No branch." + branchName + ".remote item in the .git/config"); + return null; + } + boolean merge = mergeName != null; + String remoteBranch = (merge ? mergeName : rebaseName); + + GitRemote branchRemote = null; + for (GitRemote remote : remotes) { + if (remote.getName().equals(remoteName)) { + branchRemote = remote; + break; + } + } + if (branchRemote == null) { + LOG.info("No remote found with name " + remoteName); + return null; + } + + return new GitBranchTrackInfo(branchName, branchRemote, remoteBranch, merge); + } + + @Nullable + private static BranchConfig parseBranchSection(String sectionName, Profile.Section section, ClassLoader classLoader) { + BranchBean branchBean = section.as(BranchBean.class, classLoader); + Matcher matcher = BRANCH_SECTION.matcher(sectionName); + if (matcher.matches()) { + return new BranchConfig(matcher.group(1), branchBean); + } + LOG.error(String.format("Invalid branch section format in .git/config. sectionName: %s section: %s", sectionName, section)); + return null; + } + + private static Collection parseRemotes(Ini ini, ClassLoader classLoader) { Collection remotes = new ArrayList(); Collection urls = new ArrayList(); for (Map.Entry stringSectionEntry : ini.entrySet()) { @@ -122,9 +205,7 @@ class GitConfig { } } - Collection gitRemotes = makeGitRemotes(remotes, urls); - return new GitConfig(gitRemotes); - + return makeGitRemotes(remotes, urls); } // populate GitRemotes with substituting urls when needed @@ -345,6 +426,30 @@ class GitConfig { @Nullable String getInsteadOf(); @Nullable String getPushInsteadOf(); } + + private static class BranchConfig { + private final String myName; + private final BranchBean myBean; + + public BranchConfig(String name, BranchBean bean) { + myName = name; + myBean = bean; + } + + public String getName() { + return myName; + } + + public BranchBean getBean() { + return myBean; + } + } + + private interface BranchBean { + @Nullable String getRemote(); + @Nullable String getMerge(); + @Nullable String getRebase(); + } @NotNull private static String notNull(@Nullable String s) { diff --git a/plugins/git4idea/testData/config/branch/b0_no/b0_config.txt b/plugins/git4idea/testData/config/branch/b0_no/b0_config.txt new file mode 100644 index 000000000000..af107929f2da --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b0_no/b0_config.txt @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/plugins/git4idea/testData/config/branch/b0_no/b0_desc.txt b/plugins/git4idea/testData/config/branch/b0_no/b0_desc.txt new file mode 100644 index 000000000000..da5842a6ef7b --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b0_no/b0_desc.txt @@ -0,0 +1 @@ +b0 No branches \ No newline at end of file diff --git a/plugins/git4idea/testData/config/r0_no/r0_result.txt b/plugins/git4idea/testData/config/branch/b0_no/b0_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r0_no/r0_result.txt rename to plugins/git4idea/testData/config/branch/b0_no/b0_result.txt diff --git a/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_config.txt b/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_config.txt new file mode 100644 index 000000000000..8eee9225b5cc --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_config.txt @@ -0,0 +1,14 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/loki/temp/parent.git +[branch "unexistant_remote"] + remote = unexistant + merge = refs/heads/master +[branch "no_merge_item"] + remote = origin \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_desc.txt b/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_desc.txt new file mode 100644 index 000000000000..b607b5f18161 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_desc.txt @@ -0,0 +1,2 @@ +b1 No valid branches +One with incorrect remote, other without merge/rebase item \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_result.txt b/plugins/git4idea/testData/config/branch/b1_no_remotes_or_no_merge/b1_result.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/git4idea/testData/config/branch/b2_one/b2_config.txt b/plugins/git4idea/testData/config/branch/b2_one/b2_config.txt new file mode 100644 index 000000000000..59de1dea4b04 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b2_one/b2_config.txt @@ -0,0 +1,12 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = git@git.labs.intellij.net:idea/community +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/plugins/git4idea/testData/config/branch/b2_one/b2_desc.txt b/plugins/git4idea/testData/config/branch/b2_one/b2_desc.txt new file mode 100644 index 000000000000..cc57fd61e33a --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b2_one/b2_desc.txt @@ -0,0 +1 @@ +b2 One branch \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b2_one/b2_result.txt b/plugins/git4idea/testData/config/branch/b2_one/b2_result.txt new file mode 100644 index 000000000000..77e04be9712f --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b2_one/b2_result.txt @@ -0,0 +1,6 @@ +BRANCH +master +origin git@git.labs.intellij.net:idea/community git@git.labs.intellij.net:idea/community +refs/heads/*:refs/remotes/origin/* +refs/heads/*:refs/remotes/origin/* +refs/heads/master +origin/master +merge \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_config.txt b/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_config.txt new file mode 100644 index 000000000000..8965d12d3c97 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_config.txt @@ -0,0 +1,20 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = git@git.labs.intellij.net:idea/community +[remote "github"] + fetch = +refs/heads/*:refs/remotes/github/* + url = https://github.com/JetBrains/intellij-community.git + +[branch "master"] + remote = origin + merge = refs/heads/master +[branch "github_feature"] + remote = github + rebase = refs/heads/feature diff --git a/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_desc.txt b/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_desc.txt new file mode 100644 index 000000000000..22bc285c51dd --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_desc.txt @@ -0,0 +1,2 @@ +b3 Two different branches +Two valid branches with 2 remotes. One merge, second rebase. \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_result.txt b/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_result.txt new file mode 100644 index 000000000000..cb9e2f5463e5 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b3_two_and_rebase/b3_result.txt @@ -0,0 +1,12 @@ +BRANCH +master +origin git@git.labs.intellij.net:idea/community git@git.labs.intellij.net:idea/community +refs/heads/*:refs/remotes/origin/* +refs/heads/*:refs/remotes/origin/* +refs/heads/master +origin/master +merge +BRANCH +github_feature +github https://github.com/JetBrains/intellij-community.git https://github.com/JetBrains/intellij-community.git +refs/heads/*:refs/remotes/github/* +refs/heads/*:refs/remotes/github/* +refs/heads/feature +github/feature +rebase diff --git a/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_config.txt b/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_config.txt new file mode 100644 index 000000000000..40b8c1998a68 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_config.txt @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = git@git.labs.intellij.net:idea/community +[branch "master"] + remote = origin + merge = refs/heads/master + rebase = refs/heads/master diff --git a/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_desc.txt b/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_desc.txt new file mode 100644 index 000000000000..a2029c60ff0c --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_desc.txt @@ -0,0 +1,2 @@ +b4 Branch with both merge and rebase +Then only merge is taken into consideration. \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_result.txt b/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_result.txt new file mode 100644 index 000000000000..77e04be9712f --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b4_merge_and_rebase/b4_result.txt @@ -0,0 +1,6 @@ +BRANCH +master +origin git@git.labs.intellij.net:idea/community git@git.labs.intellij.net:idea/community +refs/heads/*:refs/remotes/origin/* +refs/heads/*:refs/remotes/origin/* +refs/heads/master +origin/master +merge \ No newline at end of file diff --git a/plugins/git4idea/testData/config/r0_no/r0_config.txt b/plugins/git4idea/testData/config/remote/r0_no/r0_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r0_no/r0_config.txt rename to plugins/git4idea/testData/config/remote/r0_no/r0_config.txt diff --git a/plugins/git4idea/testData/config/r0_no/r0_desc.txt b/plugins/git4idea/testData/config/remote/r0_no/r0_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r0_no/r0_desc.txt rename to plugins/git4idea/testData/config/remote/r0_no/r0_desc.txt diff --git a/plugins/git4idea/testData/config/remote/r0_no/r0_result.txt b/plugins/git4idea/testData/config/remote/r0_no/r0_result.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/git4idea/testData/config/r1_one/r1_config.txt b/plugins/git4idea/testData/config/remote/r1_one/r1_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r1_one/r1_config.txt rename to plugins/git4idea/testData/config/remote/r1_one/r1_config.txt diff --git a/plugins/git4idea/testData/config/r1_one/r1_desc.txt b/plugins/git4idea/testData/config/remote/r1_one/r1_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r1_one/r1_desc.txt rename to plugins/git4idea/testData/config/remote/r1_one/r1_desc.txt diff --git a/plugins/git4idea/testData/config/r1_one/r1_result.txt b/plugins/git4idea/testData/config/remote/r1_one/r1_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r1_one/r1_result.txt rename to plugins/git4idea/testData/config/remote/r1_one/r1_result.txt diff --git a/plugins/git4idea/testData/config/r2_two/r2_config.txt b/plugins/git4idea/testData/config/remote/r2_two/r2_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r2_two/r2_config.txt rename to plugins/git4idea/testData/config/remote/r2_two/r2_config.txt diff --git a/plugins/git4idea/testData/config/r2_two/r2_desc.txt b/plugins/git4idea/testData/config/remote/r2_two/r2_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r2_two/r2_desc.txt rename to plugins/git4idea/testData/config/remote/r2_two/r2_desc.txt diff --git a/plugins/git4idea/testData/config/r2_two/r2_result.txt b/plugins/git4idea/testData/config/remote/r2_two/r2_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r2_two/r2_result.txt rename to plugins/git4idea/testData/config/remote/r2_two/r2_result.txt diff --git a/plugins/git4idea/testData/config/r3_pushurl/r3_config.txt b/plugins/git4idea/testData/config/remote/r3_pushurl/r3_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r3_pushurl/r3_config.txt rename to plugins/git4idea/testData/config/remote/r3_pushurl/r3_config.txt diff --git a/plugins/git4idea/testData/config/r3_pushurl/r3_desc.txt b/plugins/git4idea/testData/config/remote/r3_pushurl/r3_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r3_pushurl/r3_desc.txt rename to plugins/git4idea/testData/config/remote/r3_pushurl/r3_desc.txt diff --git a/plugins/git4idea/testData/config/r3_pushurl/r3_result.txt b/plugins/git4idea/testData/config/remote/r3_pushurl/r3_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r3_pushurl/r3_result.txt rename to plugins/git4idea/testData/config/remote/r3_pushurl/r3_result.txt diff --git a/plugins/git4idea/testData/config/r4_insteadof/r4_config.txt b/plugins/git4idea/testData/config/remote/r4_insteadof/r4_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r4_insteadof/r4_config.txt rename to plugins/git4idea/testData/config/remote/r4_insteadof/r4_config.txt diff --git a/plugins/git4idea/testData/config/r4_insteadof/r4_desc.txt b/plugins/git4idea/testData/config/remote/r4_insteadof/r4_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r4_insteadof/r4_desc.txt rename to plugins/git4idea/testData/config/remote/r4_insteadof/r4_desc.txt diff --git a/plugins/git4idea/testData/config/r4_insteadof/r4_result.txt b/plugins/git4idea/testData/config/remote/r4_insteadof/r4_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r4_insteadof/r4_result.txt rename to plugins/git4idea/testData/config/remote/r4_insteadof/r4_result.txt diff --git a/plugins/git4idea/testData/config/r5_pushinsteadof/r5_config.txt b/plugins/git4idea/testData/config/remote/r5_pushinsteadof/r5_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r5_pushinsteadof/r5_config.txt rename to plugins/git4idea/testData/config/remote/r5_pushinsteadof/r5_config.txt diff --git a/plugins/git4idea/testData/config/r5_pushinsteadof/r5_desc.txt b/plugins/git4idea/testData/config/remote/r5_pushinsteadof/r5_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r5_pushinsteadof/r5_desc.txt rename to plugins/git4idea/testData/config/remote/r5_pushinsteadof/r5_desc.txt diff --git a/plugins/git4idea/testData/config/r5_pushinsteadof/r5_result.txt b/plugins/git4idea/testData/config/remote/r5_pushinsteadof/r5_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r5_pushinsteadof/r5_result.txt rename to plugins/git4idea/testData/config/remote/r5_pushinsteadof/r5_result.txt diff --git a/plugins/git4idea/testData/config/r6_two_urls/r6_config.txt b/plugins/git4idea/testData/config/remote/r6_two_urls/r6_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r6_two_urls/r6_config.txt rename to plugins/git4idea/testData/config/remote/r6_two_urls/r6_config.txt diff --git a/plugins/git4idea/testData/config/r6_two_urls/r6_desc.txt b/plugins/git4idea/testData/config/remote/r6_two_urls/r6_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r6_two_urls/r6_desc.txt rename to plugins/git4idea/testData/config/remote/r6_two_urls/r6_desc.txt diff --git a/plugins/git4idea/testData/config/r6_two_urls/r6_result.txt b/plugins/git4idea/testData/config/remote/r6_two_urls/r6_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r6_two_urls/r6_result.txt rename to plugins/git4idea/testData/config/remote/r6_two_urls/r6_result.txt diff --git a/plugins/git4idea/testData/config/r7_empty_insteadof/r7_config.txt b/plugins/git4idea/testData/config/remote/r7_empty_insteadof/r7_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r7_empty_insteadof/r7_config.txt rename to plugins/git4idea/testData/config/remote/r7_empty_insteadof/r7_config.txt diff --git a/plugins/git4idea/testData/config/r7_empty_insteadof/r7_desc.txt b/plugins/git4idea/testData/config/remote/r7_empty_insteadof/r7_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r7_empty_insteadof/r7_desc.txt rename to plugins/git4idea/testData/config/remote/r7_empty_insteadof/r7_desc.txt diff --git a/plugins/git4idea/testData/config/r7_empty_insteadof/r7_result.txt b/plugins/git4idea/testData/config/remote/r7_empty_insteadof/r7_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r7_empty_insteadof/r7_result.txt rename to plugins/git4idea/testData/config/remote/r7_empty_insteadof/r7_result.txt diff --git a/plugins/git4idea/testData/config/r8_insteadof_pushurl/r8_config.txt b/plugins/git4idea/testData/config/remote/r8_insteadof_pushurl/r8_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r8_insteadof_pushurl/r8_config.txt rename to plugins/git4idea/testData/config/remote/r8_insteadof_pushurl/r8_config.txt diff --git a/plugins/git4idea/testData/config/r8_insteadof_pushurl/r8_desc.txt b/plugins/git4idea/testData/config/remote/r8_insteadof_pushurl/r8_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r8_insteadof_pushurl/r8_desc.txt rename to plugins/git4idea/testData/config/remote/r8_insteadof_pushurl/r8_desc.txt diff --git a/plugins/git4idea/testData/config/r8_insteadof_pushurl/r8_result.txt b/plugins/git4idea/testData/config/remote/r8_insteadof_pushurl/r8_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r8_insteadof_pushurl/r8_result.txt rename to plugins/git4idea/testData/config/remote/r8_insteadof_pushurl/r8_result.txt diff --git a/plugins/git4idea/testData/config/r9_one_capitalized/r9_config.txt b/plugins/git4idea/testData/config/remote/r9_one_capitalized/r9_config.txt similarity index 100% rename from plugins/git4idea/testData/config/r9_one_capitalized/r9_config.txt rename to plugins/git4idea/testData/config/remote/r9_one_capitalized/r9_config.txt diff --git a/plugins/git4idea/testData/config/r9_one_capitalized/r9_desc.txt b/plugins/git4idea/testData/config/remote/r9_one_capitalized/r9_desc.txt similarity index 100% rename from plugins/git4idea/testData/config/r9_one_capitalized/r9_desc.txt rename to plugins/git4idea/testData/config/remote/r9_one_capitalized/r9_desc.txt diff --git a/plugins/git4idea/testData/config/r9_one_capitalized/r9_result.txt b/plugins/git4idea/testData/config/remote/r9_one_capitalized/r9_result.txt similarity index 100% rename from plugins/git4idea/testData/config/r9_one_capitalized/r9_result.txt rename to plugins/git4idea/testData/config/remote/r9_one_capitalized/r9_result.txt diff --git a/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java b/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java index fbbf060ee538..c8f53219667a 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java @@ -23,6 +23,7 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.util.*; @@ -33,11 +34,25 @@ import static org.testng.Assert.assertNotNull; */ public class GitConfigTest { - @DataProvider(name = "provider") - public Object[][] loadData() throws IOException { + @DataProvider(name = "remote") + public Object[][] loadRemotes() throws IOException { + return loadData("remote"); + } + + @DataProvider(name = "branch") + public Object[][] loadBranches() throws IOException { + return loadData("branch"); + } + + public static Object[][] loadData(String subfolder) throws IOException { File pluginRoot = new File(PluginPathManager.getPluginHomePath("git4idea")); - File dataDir = new File(new File(pluginRoot, "testData"), "config"); - File[] tests = dataDir.listFiles(); + File dataDir = new File(new File(new File(pluginRoot, "testData"), "config"), subfolder); + File[] tests = dataDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return !name.startsWith("."); + } + }); Object[][] data = new Object[tests.length][]; for (int i = 0; i < tests.length; i++) { File testDir = tests[i]; @@ -67,13 +82,44 @@ public class GitConfigTest { return data; } - @Test(dataProvider = "provider") - public void test(String testName, File configFile, File resultFile) throws IOException { + @Test(dataProvider = "remote") + public void testRemotes(String testName, File configFile, File resultFile) throws IOException { GitConfig config = GitConfig.read(configFile); - GitTestUtil.assertEqualCollections(config.getRemotes(), readResults(resultFile)); + GitTestUtil.assertEqualCollections(config.getRemotes(), readRemoteResults(resultFile)); } - private static Set readResults(File resultFile) throws IOException { + @Test(dataProvider = "branch") + public void testBranches(String testName, File configFile, File resultFile) throws IOException { + GitConfig config = GitConfig.read(configFile); + GitTestUtil.assertEqualCollections(config.getBranchTrackInfos(), readBranchResults(resultFile)); + } + + private static Collection readBranchResults(File file) throws IOException { + String content = FileUtil.loadFile(file); + Collection remotes = new ArrayList(); + String[] remStrings = content.split("BRANCH\n"); + for (String remString : remStrings) { + if (StringUtil.isEmptyOrSpaces(remString)) { + continue; + } + String[] info = remString.split("\n"); + String branch = info[0]; + GitRemote remote = getRemote(info[1]); + String remoteSpec = info[2]; + String remoteBranchName = info[3]; + boolean merge = info[4].equals("merge"); + remotes.add(new GitBranchTrackInfo(branch, remote, remoteSpec, merge)); + } + return remotes; + } + + private static GitRemote getRemote(String remoteString) { + String[] remoteInfo = remoteString.split(" "); + return new GitRemote(getOrEmpty(remoteInfo, 0), Collections.singletonList(getOrEmpty(remoteInfo, 1)), + Collections.singletonList(getOrEmpty(remoteInfo, 2)), getOrEmpty(remoteInfo, 3), getOrEmpty(remoteInfo, 4)); + } + + private static Set readRemoteResults(File resultFile) throws IOException { String content = FileUtil.loadFile(resultFile); Set remotes = new HashSet(); String[] remStrings = content.split("REMOTE\n"); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovySourceRootDetector.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovySourceRootDetector.java index 12d9045cce68..4d84be3be302 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovySourceRootDetector.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovySourceRootDetector.java @@ -15,10 +15,17 @@ */ package org.jetbrains.plugins.groovy; -import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetectionUtil; import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetector; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.tree.IElementType; import com.intellij.util.NullableFunction; +import com.intellij.util.StringBuilderSpinAllocator; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; /** * @author nik @@ -41,9 +48,47 @@ public class GroovySourceRootDetector extends JavaSourceRootDetector { return new NullableFunction() { @Override public String fun(CharSequence charSequence) { - //todo[nik] implement groovy-specific package name parsing? - return JavaSourceRootDetectionUtil.getPackageName(charSequence); + return getPackageName(charSequence); } }; } + + @Nullable + public static String getPackageName(CharSequence text) { + Lexer lexer = new GroovyLexer(); + lexer.start(text); + skipWhitespacesAndComments(lexer); + final IElementType firstToken = lexer.getTokenType(); + if (firstToken != GroovyTokenTypes.kPACKAGE) { + return ""; + } + lexer.advance(); + skipWhitespacesAndComments(lexer); + + final StringBuilder buffer = StringBuilderSpinAllocator.alloc(); + try { + while(true){ + if (lexer.getTokenType() != GroovyTokenTypes.mIDENT) break; + buffer.append(text, lexer.getTokenStart(), lexer.getTokenEnd()); + lexer.advance(); + skipWhitespacesAndComments(lexer); + if (lexer.getTokenType() != GroovyTokenTypes.mDOT) break; + buffer.append('.'); + lexer.advance(); + skipWhitespacesAndComments(lexer); + } + String packageName = buffer.toString(); + if (packageName.length() == 0 || StringUtil.endsWithChar(packageName, '.')) return null; + return packageName; + } + finally { + StringBuilderSpinAllocator.dispose(buffer); + } + } + + private static void skipWhitespacesAndComments(Lexer lexer) { + while(TokenSets.ALL_COMMENT_TOKENS.contains(lexer.getTokenType()) || TokenSets.WHITE_SPACES_SET.contains(lexer.getTokenType())) { + lexer.advance(); + } + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/ide/GroovySourceRootDetectorTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/ide/GroovySourceRootDetectorTest.groovy new file mode 100644 index 000000000000..4ff5a90bfc35 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/ide/GroovySourceRootDetectorTest.groovy @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2011 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 org.jetbrains.plugins.groovy.ide + +import junit.framework.TestCase +import org.jetbrains.plugins.groovy.GroovySourceRootDetector + +/** + * @author nik + */ +class GroovySourceRootDetectorTest extends TestCase { + public void testEmpty() { + doTest("", "") + } + + public void testComment() { + doTest("//comment", "") + doTest(" /* comment */", "") + } + + public void testStatement() { + doTest("def a = 0;", "") + } + + public void testSimplePackage() { + doTest("package simple", "simple") + doTest("package simple;", "simple") + doTest("""//comment + package simple;""", "simple") + } + + public void testComplexPackage() { + doTest("package com.simple", "com.simple") + doTest("package com.simple;", "com.simple") + doTest(""" + package com.simple;""", "com.simple") + doTest("""/** + @author nik; + */ + package com.simple;""", "com.simple") + } + + + def doTest(String text, String expectedPackageName) { + assertEquals(expectedPackageName, GroovySourceRootDetector.getPackageName(text)) + } +} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 9853b3fe4eb9..35a81ac95aa2 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -89,6 +89,8 @@ + @@ -1160,6 +1162,7 @@ +