AbiVersionIndex added

This commit is contained in:
Andrey Breslav
2013-01-24 14:46:34 +04:00
parent 8797c3ea95
commit 41dd4b29ae
3 changed files with 133 additions and 0 deletions
@@ -27,6 +27,7 @@ import org.jetbrains.jet.util.slicedmap.WritableSlice;
public class AbiVersionUtil {
public static final WritableSlice<PsiClass, Integer> ABI_VERSION_ERRORS =
new BasicWritableSlice<PsiClass, Integer>(Slices.ONLY_REWRITE_TO_EQUAL, true);
public static final int INVALID_VERSION = -1;
public static boolean isAbiVersionCompatible(int abiVersion) {
return abiVersion == JvmAbi.VERSION;
+2
View File
@@ -215,6 +215,8 @@
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetAnnotationsIndex" />
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetTopLevelShortObjectNameIndex" />
<fileBasedIndex implementation="org.jetbrains.jet.plugin.versions.KotlinAbiVersionIndex"/>
<contentBasedClassFileProcessor implementation="org.jetbrains.jet.plugin.libraries.JetContentBasedFileSubstitutor" />
<psi.clsCustomNavigationPolicy implementation="org.jetbrains.jet.plugin.libraries.JetClsNavigationPolicy" />
<psi.clsDecompiledFileProvider implementation="org.jetbrains.jet.plugin.libraries.JetClsFileDecompiledPsiFileProvider" />
@@ -0,0 +1,130 @@
/*
* Copyright 2010-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.jet.plugin.versions;
import com.google.common.collect.Maps;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.indexing.*;
import com.intellij.util.io.ExternalIntegerKeyDescriptor;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.ClassReader;
import org.jetbrains.asm4.ClassVisitor;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import java.util.Map;
/**
* Important! This is not a stub-based index. And it has its own version
*/
public class KotlinAbiVersionIndex extends ScalarIndexExtension<Integer> {
public static final KotlinAbiVersionIndex INSTANCE = new KotlinAbiVersionIndex();
private static final int VERSION = 0;
private static final ID<Integer, Void> NAME = ID.create(KotlinAbiVersionIndex.class.getCanonicalName());
private static final ExternalIntegerKeyDescriptor KEY_DESCRIPTOR = new ExternalIntegerKeyDescriptor();
private static final FileBasedIndex.InputFilter INPUT_FILTER = new FileBasedIndex.InputFilter() {
@Override
public boolean acceptInput(VirtualFile file) {
return file.getFileType() == StdFileTypes.CLASS;
}
};
private static final DataIndexer<Integer, Void, FileContent> INDEXER = new DataIndexer<Integer, Void, FileContent>() {
@NotNull
@Override
public Map<Integer, Void> map(FileContent inputData) {
final Map<Integer, Void> result = Maps.newHashMap();
final Ref<Boolean> annotationPresent = new Ref<Boolean>(false);
ClassReader classReader = new ClassReader(inputData.getContent());
classReader.accept(new ClassVisitor(Opcodes.ASM4) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (!JvmStdlibNames.JET_CLASS.getDescriptor().equals(desc) &&
!JvmStdlibNames.JET_PACKAGE_CLASS.getDescriptor().equals(desc)) {
return null;
}
annotationPresent.set(true);
return new AnnotationVisitor(Opcodes.ASM4) {
@Override
public void visit(String name, Object value) {
if (JvmStdlibNames.ABI_VERSION_NAME.equals(name)) {
if (value instanceof Integer) {
Integer abiVersion = (Integer) value;
result.put(abiVersion, null);
}
else {
// Version is set to something weird
result.put(AbiVersionUtil.INVALID_VERSION, null);
}
}
}
};
}
}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
if (annotationPresent.get() && result.isEmpty()) {
// No version at all: the class is too old
result.put(AbiVersionUtil.INVALID_VERSION, null);
}
return result;
}
};
private KotlinAbiVersionIndex() {}
@NotNull
@Override
public ID<Integer, Void> getName() {
return NAME;
}
@NotNull
@Override
public DataIndexer<Integer, Void, FileContent> getIndexer() {
return INDEXER;
}
@Override
public KeyDescriptor<Integer> getKeyDescriptor() {
return KEY_DESCRIPTOR;
}
@Override
public FileBasedIndex.InputFilter getInputFilter() {
return INPUT_FILTER;
}
@Override
public boolean dependsOnFileContent() {
return true;
}
@Override
public int getVersion() {
return VERSION;
}
}