diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index fb0427ec800e..27e02a867918 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -299,6 +299,13 @@ public def layoutCommunityPlugins(String home) { } } + jar("artifact-resolver-m31.jar") { + module("maven-artifact-resolver-m31") + module("maven-artifact-resolver-m2") { + include(name: 'org/jetbrains/idea/maven/artifactResolver/common/*') + } + } + dir("maven3") { fileset(dir: "$home/plugins/maven/maven3-server-impl/lib") {include(name: "*.jar")} fileset(dir: "$home/plugins/maven/maven3-server-impl/lib/maven3/lib") {include(name: "*.jar")} diff --git a/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass.log b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass.log new file mode 100644 index 000000000000..228bc41f8f7e --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass.log @@ -0,0 +1,11 @@ +Compiling files: +src/package2/A.java +End of files +Cleaning output files: +out/production/AddClassHidingImportedClass/package2/B.class +out/production/AddClassHidingImportedClass/package3/C.class +End of files +Compiling files: +src/package2/B.java +src/package3/C.java +End of files diff --git a/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package1/A.java b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package1/A.java new file mode 100644 index 000000000000..a61ecd9b2705 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package1/A.java @@ -0,0 +1,7 @@ +package package1; + +public class A { + public static class D { + public final String s = new String("package1"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package2/A.java.new b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package2/A.java.new new file mode 100644 index 000000000000..98b0feeffca2 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package2/A.java.new @@ -0,0 +1,7 @@ +package package2; + +public class A { + public static class D { + public final String s = new String("package2"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package2/B.java b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package2/B.java new file mode 100644 index 000000000000..a32b694a09c8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package2/B.java @@ -0,0 +1,6 @@ +package package2; +import package1.*; + +public class B extends A{ + +} diff --git a/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package3/C.java b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package3/C.java new file mode 100644 index 000000000000..04d86d390ea6 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/addClassHidingImportedClass/src/package3/C.java @@ -0,0 +1,14 @@ +package package3; + +import package2.B; + +public class C { + + public B.D p; + + public String get() { + p = new B.D(); + return p.s; + } + +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java index fdc84abf785f..154d5daa6215 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java @@ -321,15 +321,17 @@ public class ClassRepr extends Proto { } public String getPackageName() { - return getPackageName(name); + final String strValue = myContext.getValue(name); + return strValue != null? getPackageName(strValue) : null; } - public String getPackageName(final int s) { - return getPackageName(myContext.getValue(s)); + public String getShortName() { + final String strValue = myContext.getValue(name); + return strValue != null? getShortName(strValue) : null; } @NotNull - public static String getPackageName(final String raw) { + public static String getPackageName(@NotNull final String raw) { final int index = raw.lastIndexOf('/'); if (index == -1) { @@ -339,6 +341,17 @@ public class ClassRepr extends Proto { return raw.substring(0, index); } + @NotNull + public static String getShortName(@NotNull final String fqName) { + final int index = fqName.lastIndexOf('/'); + + if (index == -1) { + return fqName; + } + + return fqName.substring(index + 1); + } + @Nullable public FieldRepr findField(final int name) { for (FieldRepr f : myFields) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java index 29c92aa7a916..8d178ad46990 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java @@ -45,6 +45,7 @@ public class Mappings { private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab"; private final static String CLASS_TO_CLASS = "classToClass.tab"; + private final static String SHORT_NAMES = "shortNames.tab"; private final static String SOURCE_TO_CLASS = "sourceToClass.tab"; private final static String CLASS_TO_SOURCE = "classToSource.tab"; private static final IntInlineKeyDescriptor INT_KEY_DESCRIPTOR = new IntInlineKeyDescriptor(); @@ -65,6 +66,7 @@ public class Mappings { private final TIntHashSet myChangedClasses; private final THashSet myChangedFiles; private final Set myDeletedClasses; + private final Set myAddedClasses; private final Object myLock; private final File myRootDir; @@ -83,6 +85,10 @@ public class Mappings { private IntIntMultiMaplet myClassToClassDependency; private ObjectObjectMultiMaplet mySourceFileToClasses; private IntObjectMaplet myClassToSourceFile; + /** + * [short className] -> list of FQ names + */ + private IntIntMultiMaplet myShortClassNameIndex; private IntIntTransientMultiMaplet myRemovedSuperClasses; private IntIntTransientMultiMaplet myAddedSuperClasses; @@ -96,6 +102,7 @@ public class Mappings { myChangedClasses = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR); myChangedFiles = new THashSet(FileUtil.FILE_HASHING_STRATEGY); myDeletedClasses = new HashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR); + myAddedClasses = new HashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR); myDeltaIsTransient = base.myDeltaIsTransient; myRootDir = new File(FileUtil.toSystemIndependentName(base.myRootDir.getAbsolutePath()) + File.separatorChar + "myDelta"); myContext = base.myContext; @@ -112,6 +119,7 @@ public class Mappings { myChangedClasses = null; myChangedFiles = null; myDeletedClasses = null; + myAddedClasses = null; myDeltaIsTransient = transientDelta; myRootDir = rootDir; createImplementation(); @@ -132,6 +140,7 @@ public class Mappings { if (myIsDelta && myDeltaIsTransient) { myClassToSubclasses = new IntIntTransientMultiMaplet(); myClassToClassDependency = new IntIntTransientMultiMaplet(); + myShortClassNameIndex = null; mySourceFileToClasses = new ObjectObjectTransientMultiMaplet(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor); myClassToSourceFile = new IntObjectTransientMaplet(); } @@ -141,6 +150,7 @@ public class Mappings { } myClassToSubclasses = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_SUBCLASSES), INT_KEY_DESCRIPTOR); myClassToClassDependency = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_CLASS), INT_KEY_DESCRIPTOR); + myShortClassNameIndex = myIsDelta? null : new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, SHORT_NAMES), INT_KEY_DESCRIPTOR); mySourceFileToClasses = new ObjectObjectPersistentMultiMaplet( DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext), ourClassSetConstructor @@ -1788,36 +1798,51 @@ public class Mappings { for (final ClassRepr c : addedClasses) { debug("Class name: ", c.name); - myDelta.addChangedClass(c.name); + myDelta.addAddedClass(c); for (final int sup : c.getSupers()) { myDelta.registerAddedSuperClass(c.name, sup); } - if (!myEasyMode) { - final TIntHashSet depClasses = myClassToClassDependency.get(c.name); - - if (depClasses != null) { - depClasses.forEach(new TIntProcedure() { - @Override - public boolean execute(int depClass) { - final File fName = myClassToSourceFile.get(depClass); - if (fName != null) { - if (myFilter == null || myFilter.accept(fName)) { - debug("Adding dependent file ", fName); - myAffectedFiles.add(fName); - } - } - return true; - } - }); + if (!myEasyMode && !c.isAnonymous() && !c.isLocal()) { + final TIntHashSet toAffect = new TIntHashSet(); + toAffect.add(c.name); + final TIntHashSet classes = myShortClassNameIndex.get(myContext.get(c.getShortName())); + if (classes != null) { + // affecting dependencies on all other classes with the same short name + toAffect.addAll(classes.toArray()); } + toAffect.forEach(new TIntProcedure() { + public boolean execute(int qName) { + final TIntHashSet depClasses = myClassToClassDependency.get(qName); + if (depClasses != null) { + affectCorrespondingSourceFiles(depClasses); + } + return true; + } + }); } } debug("End of added classes processing."); } + private void affectCorrespondingSourceFiles(TIntHashSet toAffect) { + toAffect.forEach(new TIntProcedure() { + @Override + public boolean execute(int depClass) { + final File fName = myClassToSourceFile.get(depClass); + if (fName != null) { + if (myFilter == null || myFilter.accept(fName)) { + debug("Adding dependent file ", fName); + myAffectedFiles.add(fName); + } + } + return true; + } + }); + } + private void calculateAffectedFiles(final DiffState state) { debug("Checking dependent classes:"); @@ -1979,10 +2004,7 @@ public class Mappings { } } - private void cleanupRemovedClass(final Mappings delta, - @NotNull final ClassRepr cr, - final Set usages, - final IntIntMultiMaplet dependenciesTrashBin) { + private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, final Set usages, final IntIntMultiMaplet dependenciesTrashBin) { final int className = cr.name; for (final int superSomething : cr.getSupers()) { @@ -1994,6 +2016,9 @@ public class Mappings { myClassToClassDependency.remove(className); myClassToSubclasses.remove(className); myClassToSourceFile.remove(className); + if (!cr.isLocal() && !cr.isAnonymous()) { + myShortClassNameIndex.removeFrom(myContext.get(cr.getShortName()), className); + } } public void integrate(final Mappings delta) { @@ -2025,6 +2050,11 @@ public class Mappings { for (final ClassRepr repr : delta.getDeletedClasses()) { cleanupRemovedClass(delta, repr, repr.getUsages(), dependenciesTrashBin); } + for (ClassRepr repr : delta.getAddedClasses()) { + if (!repr.isAnonymous() && !repr.isLocal()) { + myShortClassNameIndex.put(myContext.get(repr.getShortName()), repr.name); + } + } final TIntHashSet superClasses = new TIntHashSet(); final IntIntTransientMultiMaplet addedSuperClasses = delta.getAddedSuperClasses(); @@ -2090,6 +2120,16 @@ public class Mappings { myClassToSubclasses.putAll(delta.myClassToSubclasses); myClassToSourceFile.putAll(delta.myClassToSourceFile); mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses); + delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure>() { + public boolean execute(File src, Collection classes) { + for (ClassRepr repr : classes) { + if (!repr.isAnonymous() && !repr.isLocal()) { + myShortClassNameIndex.put(myContext.get(repr.getShortName()), repr.name); + } + } + return true; + } + }); } // updating classToClass dependencies @@ -2224,6 +2264,7 @@ public class Mappings { myClassToSourceFile.close(); if (!myIsDelta) { + myShortClassNameIndex.close(); // only close if you own the context final DependencyContext context = myContext; if (context != null) { @@ -2247,6 +2288,7 @@ public class Mappings { myClassToSourceFile.flush(memoryCachesOnly); if (!myIsDelta) { + myShortClassNameIndex.flush(memoryCachesOnly); // flush if you own the context final DependencyContext context = myContext; if (context != null) { @@ -2312,6 +2354,14 @@ public class Mappings { addChangedClass(cr.name); } + private void addAddedClass(final ClassRepr cr) { + assert (myAddedClasses != null); + + myAddedClasses.add(cr); + + addChangedClass(cr.name); + } + private void addChangedClass(final int it) { assert (myChangedClasses != null && myChangedFiles != null); myChangedClasses.add(it); @@ -2328,6 +2378,11 @@ public class Mappings { return myDeletedClasses == null ? Collections.emptySet() : Collections.unmodifiableSet(myDeletedClasses); } + @NotNull + private Set getAddedClasses() { + return myAddedClasses == null ? Collections.emptySet() : Collections.unmodifiableSet(myAddedClasses); + } + private TIntHashSet getChangedClasses() { return myChangedClasses; } @@ -2390,6 +2445,7 @@ public class Mappings { myClassToClassDependency, mySourceFileToClasses, myClassToSourceFile, + myShortClassNameIndex }; final String[] info = { @@ -2397,6 +2453,7 @@ public class Mappings { "ClassToClassDependency", "SourceFileToClasses", "ClassToSourceFile", + "ShortClassNameIndex" }; for (int i = 0; i < data.length; i++) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java index 1a0ce3bdc1d6..791e2e291f73 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java @@ -41,7 +41,7 @@ import java.util.concurrent.ConcurrentMap; * Date: 10/7/11 */ public class BuildDataManager implements StorageOwner { - private static final int VERSION = 20; + private static final int VERSION = 21; private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager"); private static final String SRC_TO_FORM_STORAGE = "src-form"; private static final String MAPPINGS_STORAGE = "mappings"; diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java index 8f97b867cdbd..7adfbea6124f 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java @@ -113,4 +113,9 @@ public class CommonTest extends IncrementalTestCase { public void testAddDuplicateClass() throws Exception { doTest(); } + + public void testAddClassHidingImportedClass() throws Exception { + doTest(); + } + } diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java index 9721e1b00b36..45622f0532c6 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -23,7 +23,6 @@ import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.editor.Document; @@ -114,6 +113,13 @@ public class FindInProjectUtil { if (model.getModuleName() == null || editor == null) { model.setDirectoryName(directoryName); model.setProjectScope(directoryName == null && module == null && !model.isCustomScope() || editor != null); + + // for convenience set directory name to directory of current file, note that we doesn't change default projectScope + if (directoryName == null) { + VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext); + if (virtualFile != null && !virtualFile.isDirectory()) virtualFile = virtualFile.getParent(); + if (virtualFile != null) model.setDirectoryName(virtualFile.getPresentableUrl()); + } } } diff --git a/plugins/maven/artifact-resolver-m2/src/org/jetbrains/idea/maven/artifactResolver/common/MavenModuleMap.java b/plugins/maven/artifact-resolver-m2/src/org/jetbrains/idea/maven/artifactResolver/common/MavenModuleMap.java index f9246328b8c1..bf3fff93b063 100644 --- a/plugins/maven/artifact-resolver-m2/src/org/jetbrains/idea/maven/artifactResolver/common/MavenModuleMap.java +++ b/plugins/maven/artifact-resolver-m2/src/org/jetbrains/idea/maven/artifactResolver/common/MavenModuleMap.java @@ -56,6 +56,10 @@ public class MavenModuleMap { public boolean resolveToModule(Artifact artifact) { String extension = artifact.getArtifactHandler().getExtension(); + if ("jar".equals(extension) && "test-jar".equals(artifact.getType())) { + extension = "test-jar"; + } + File file = findArtifact(artifact.getGroupId(), artifact.getArtifactId(), extension, artifact.getBaseVersion()); if(file == null) { diff --git a/plugins/maven/artifact-resolver-m3/src/org/jetbrains/idea/maven/artifactResolver/MyWorkspaceReader.java b/plugins/maven/artifact-resolver-m3/src/org/jetbrains/idea/maven/artifactResolver/MyWorkspaceReader.java index d67fcc9f0a12..612d24bb8b7d 100644 --- a/plugins/maven/artifact-resolver-m3/src/org/jetbrains/idea/maven/artifactResolver/MyWorkspaceReader.java +++ b/plugins/maven/artifact-resolver-m3/src/org/jetbrains/idea/maven/artifactResolver/MyWorkspaceReader.java @@ -52,7 +52,12 @@ public class MyWorkspaceReader implements WorkspaceReader { } public File findArtifact(Artifact artifact) { - return MavenModuleMap.getInstance().findArtifact(artifact.getGroupId(), artifact.getArtifactId(), artifact.getExtension(), + String type = artifact.getExtension(); + if ("jar".equals(type) && "tests".equals(artifact.getClassifier())) { + type = "test-jar"; + } + + return MavenModuleMap.getInstance().findArtifact(artifact.getGroupId(), artifact.getArtifactId(), type, artifact.getBaseVersion()); } diff --git a/plugins/maven/artifact-resolver-m31/lib/eclipse-aether/aether-api-0.9.0.M2.jar b/plugins/maven/artifact-resolver-m31/lib/eclipse-aether/aether-api-0.9.0.M2.jar new file mode 100644 index 000000000000..e5b122cec252 Binary files /dev/null and b/plugins/maven/artifact-resolver-m31/lib/eclipse-aether/aether-api-0.9.0.M2.jar differ diff --git a/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml b/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml new file mode 100644 index 000000000000..3d45f6bed168 --- /dev/null +++ b/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/maven/artifact-resolver-m31/src/META-INF/plexus/components.xml b/plugins/maven/artifact-resolver-m31/src/META-INF/plexus/components.xml new file mode 100644 index 000000000000..d4d29b1060f7 --- /dev/null +++ b/plugins/maven/artifact-resolver-m31/src/META-INF/plexus/components.xml @@ -0,0 +1,12 @@ + + + + + org.eclipse.aether.repository.WorkspaceReader + ide + org.jetbrains.idea.maven.artifactResolver.IntelliJWorkspaceReaderM31 + + false + + + diff --git a/plugins/maven/artifact-resolver-m31/src/org/jetbrains/idea/maven/artifactResolver/IntelliJWorkspaceReaderM31.java b/plugins/maven/artifact-resolver-m31/src/org/jetbrains/idea/maven/artifactResolver/IntelliJWorkspaceReaderM31.java new file mode 100644 index 000000000000..3041e8350a20 --- /dev/null +++ b/plugins/maven/artifact-resolver-m31/src/org/jetbrains/idea/maven/artifactResolver/IntelliJWorkspaceReaderM31.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2013 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.idea.maven.artifactResolver; + +import org.codehaus.plexus.component.annotations.Component; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.repository.WorkspaceReader; +import org.eclipse.aether.repository.WorkspaceRepository; +import org.jetbrains.idea.maven.artifactResolver.common.MavenModuleMap; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +/** + * @author Sergey Evdokimov + */ +@Component(role = WorkspaceReader.class, hint = "ide") +public class IntelliJWorkspaceReaderM31 implements WorkspaceReader { + + private final WorkspaceRepository myWorkspaceRepository; + + public IntelliJWorkspaceReaderM31() { + myWorkspaceRepository = new WorkspaceRepository("ide", getClass()); + } + + @Override + public int hashCode() { + return 311; + } + + @Override + public boolean equals(Object o) { + return o instanceof IntelliJWorkspaceReaderM31; + } + + public WorkspaceRepository getRepository() { + return myWorkspaceRepository; + } + + public File findArtifact(Artifact artifact) { + String type = artifact.getExtension(); + if ("jar".equals(type) && "tests".equals(artifact.getClassifier())) { + type = "test-jar"; + } + + return MavenModuleMap.getInstance().findArtifact(artifact.getGroupId(), artifact.getArtifactId(), type, + artifact.getBaseVersion()); + } + + public List findVersions(Artifact artifact) { + return Collections.emptyList(); + } +} diff --git a/plugins/maven/artifact-resolver-m31/src/org/jetbrains/idea/maven/artifactResolver/MavenArtifactResolvedM31RtMarker.java b/plugins/maven/artifact-resolver-m31/src/org/jetbrains/idea/maven/artifactResolver/MavenArtifactResolvedM31RtMarker.java new file mode 100644 index 000000000000..ad15baf8aae2 --- /dev/null +++ b/plugins/maven/artifact-resolver-m31/src/org/jetbrains/idea/maven/artifactResolver/MavenArtifactResolvedM31RtMarker.java @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2013 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.idea.maven.artifactResolver; + +/** + * @author Sergey Evdokimov + */ +public class MavenArtifactResolvedM31RtMarker { +} diff --git a/plugins/maven/maven.iml b/plugins/maven/maven.iml index 8c58bb720940..c15aa891282b 100644 --- a/plugins/maven/maven.iml +++ b/plugins/maven/maven.iml @@ -59,6 +59,7 @@ + diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java index a8f4606d176c..181537bd3e56 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java @@ -47,6 +47,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.artifactResolver.MavenArtifactResolvedM2RtMarker; +import org.jetbrains.idea.maven.artifactResolver.MavenArtifactResolvedM31RtMarker; import org.jetbrains.idea.maven.artifactResolver.MavenArtifactResolvedM3RtMarker; import org.jetbrains.idea.maven.artifactResolver.common.MavenModuleMap; import org.jetbrains.idea.maven.project.MavenGeneralSettings; @@ -126,7 +127,7 @@ public class MavenExternalParameters { if (project != null && parameters.isResolveToWorkspace()) { try { - String resolverJar = getArtifactResolverJar(MavenUtil.isMaven3(mavenHome)); + String resolverJar = getArtifactResolverJar(MavenUtil.getMavenVersion(mavenHome)); confFile = patchConfFile(confFile, resolverJar); File modulesPathsFile = dumpModulesPaths(project); @@ -196,11 +197,24 @@ public class MavenExternalParameters { finally { sc.close(); } - } - private static String getArtifactResolverJar(boolean isMaven3) throws IOException { - Class marker = isMaven3 ? MavenArtifactResolvedM3RtMarker.class : MavenArtifactResolvedM2RtMarker.class; + private static String getArtifactResolverJar(@Nullable String mavenVersion) throws IOException { + boolean isMaven3; + Class marker; + + if (mavenVersion != null && mavenVersion.compareTo("3.1.0") >= 0) { + isMaven3 = true; + marker = MavenArtifactResolvedM31RtMarker.class; + } + else if (mavenVersion != null && mavenVersion.compareTo("3.0.0") >= 0) { + isMaven3 = true; + marker = MavenArtifactResolvedM3RtMarker.class; + } + else { + isMaven3 = false; + marker = MavenArtifactResolvedM2RtMarker.class; + } File classDirOrJar = new File(PathUtil.getJarPathForClass(marker)); @@ -246,6 +260,12 @@ public class MavenExternalParameters { + ':' + mavenProject.getMavenId().getVersion(), mavenProject.getFile().getPath()); + res.setProperty(mavenProject.getMavenId().getGroupId() + + ':' + mavenProject.getMavenId().getArtifactId() + + ":test-jar" + + ':' + mavenProject.getMavenId().getVersion(), + mavenProject.getTestOutputDirectory()); + res.setProperty(mavenProject.getMavenId().getGroupId() + ':' + mavenProject.getMavenId().getArtifactId() + ':' + mavenProject.getPackaging() diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index 5ee3ef7d582e..28289e0443db 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -637,6 +637,7 @@ PARSE.expected.comma=',' expected PARSE.expected.colon=':' expected PARSE.expected.rpar=')' expected PARSE.expected.lpar='(' expected +PARSE.expected.rbrace='}' expected PARSE.expected.tick='`' (backtick) expected PARSE.expected.name=name expected PARSE.expected.colon.or.rbracket=':' or ']' expected diff --git a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java index 65c791a33aed..790b1556fa74 100644 --- a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java +++ b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java @@ -236,7 +236,7 @@ public class ExpressionParsing extends Parsing { break; } } - myBuilder.advanceLexer(); + checkMatches(PyTokenTypes.RBRACE, message("PARSE.expected.rbrace")); startMarker.done(PyElementTypes.DICT_LITERAL_EXPRESSION); } } @@ -264,7 +264,7 @@ public class ExpressionParsing extends Parsing { break; } } - myBuilder.advanceLexer(); + checkMatches(PyTokenTypes.RBRACE, message("PARSE.expected.rbrace")); startMarker.done(PyElementTypes.SET_LITERAL_EXPRESSION); } diff --git a/python/testData/completion/identifiersInPlainDocstring.after.py b/python/testData/completion/identifiersInPlainDocstring.after.py deleted file mode 100644 index 440570bceefc..000000000000 --- a/python/testData/completion/identifiersInPlainDocstring.after.py +++ /dev/null @@ -1,2 +0,0 @@ -def foo(bar): - """ Variable bar """ \ No newline at end of file diff --git a/python/testData/psi/NotClosedBraceDict.py b/python/testData/psi/NotClosedBraceDict.py new file mode 100644 index 000000000000..9a726249b003 --- /dev/null +++ b/python/testData/psi/NotClosedBraceDict.py @@ -0,0 +1,3 @@ +a = { + 'b': 'c', + ] \ No newline at end of file diff --git a/python/testData/psi/NotClosedBraceDict.txt b/python/testData/psi/NotClosedBraceDict.txt new file mode 100644 index 000000000000..1222ea39bdc6 --- /dev/null +++ b/python/testData/psi/NotClosedBraceDict.txt @@ -0,0 +1,24 @@ +PyFile:NotClosedBraceDict.py + PyAssignmentStatement + PyTargetExpression: a + PsiElement(Py:IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(Py:EQ)('=') + PsiWhiteSpace(' ') + PyDictLiteralExpression + PsiElement(Py:LBRACE)('{') + PsiWhiteSpace('\n ') + PyKeyValueExpression + PyStringLiteralExpression: b + PsiElement(Py:SINGLE_QUOTED_STRING)(''b'') + PsiElement(Py:COLON)(':') + PsiWhiteSpace(' ') + PyStringLiteralExpression: c + PsiElement(Py:SINGLE_QUOTED_STRING)(''c'') + PsiElement(Py:COMMA)(',') + PsiErrorElement:'}' expected + + PsiWhiteSpace('\n ') + PsiElement(Py:RBRACKET)(']') + PsiErrorElement:Statement expected, found Py:RBRACKET + \ No newline at end of file diff --git a/python/testData/psi/NotClosedBraceSet.py b/python/testData/psi/NotClosedBraceSet.py new file mode 100644 index 000000000000..71817f2a3635 --- /dev/null +++ b/python/testData/psi/NotClosedBraceSet.py @@ -0,0 +1 @@ +a = {'b',] \ No newline at end of file diff --git a/python/testData/psi/NotClosedBraceSet.txt b/python/testData/psi/NotClosedBraceSet.txt new file mode 100644 index 000000000000..95b97f058075 --- /dev/null +++ b/python/testData/psi/NotClosedBraceSet.txt @@ -0,0 +1,17 @@ +PyFile:NotClosedBraceSet.py + PyAssignmentStatement + PyTargetExpression: a + PsiElement(Py:IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(Py:EQ)('=') + PsiWhiteSpace(' ') + PySetLiteralExpression + PsiElement(Py:LBRACE)('{') + PyStringLiteralExpression: b + PsiElement(Py:SINGLE_QUOTED_STRING)(''b'') + PsiElement(Py:COMMA)(',') + PsiErrorElement:'}' expected + + PsiElement(Py:RBRACKET)(']') + PsiErrorElement:Statement expected, found Py:RBRACKET + \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index 4f93ccad148c..da7888e80332 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -15,9 +15,12 @@ */ package com.jetbrains.python; +import com.google.common.collect.Lists; import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.jetbrains.python.documentation.DocStringFormat; import com.jetbrains.python.documentation.PyDocumentationSettings; import com.jetbrains.python.fixtures.PyTestCase; @@ -387,8 +390,10 @@ public class PythonCompletionTest extends PyTestCase { final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getModule()); settings.setFormat(DocStringFormat.PLAIN); myFixture.configureByFile("completion/identifiersInPlainDocstring.py"); - myFixture.completeBasic(); - myFixture.checkResultByFile("completion/identifiersInPlainDocstring.after.py"); + final LookupElement[] elements = myFixture.completeBasic(); + assertNotNull(elements); + assertContainsElements(Lists.newArrayList(elements), + LookupElementBuilder.create("bar").withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE)); } public void testPep328Completion() { // PY-3409 diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java index 669ac3d3906c..9f612a2539db 100644 --- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java @@ -430,6 +430,14 @@ public class PythonParsingTest extends ParsingTestCase { doTest(); } + public void testNotClosedBraceDict() { + doTest(); + } + + public void testNotClosedBraceSet() { + doTest(LanguageLevel.PYTHON33); + } + public void doTest(LanguageLevel languageLevel) { LanguageLevel prev = myLanguageLevel; myLanguageLevel = languageLevel;