mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
Binary file not shown.
@@ -375,7 +375,7 @@ public class GuessManagerImpl extends GuessManager {
|
||||
|
||||
private static class ExpressionTypeInstructionVisitor extends InstructionVisitor {
|
||||
private Map<PsiExpression, PsiType> myResult;
|
||||
private PsiElement myForPlace;
|
||||
private final PsiElement myForPlace;
|
||||
|
||||
private ExpressionTypeInstructionVisitor(PsiElement forPlace) {
|
||||
myForPlace = forPlace;
|
||||
|
||||
@@ -56,4 +56,6 @@ public interface DfaMemoryState {
|
||||
boolean checkNotNullable(DfaValue value);
|
||||
|
||||
boolean canBeNaN(DfaValue dfaValue);
|
||||
|
||||
boolean isNotNull(DfaVariableValue dfaVar);
|
||||
}
|
||||
|
||||
@@ -471,7 +471,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isNotNull(DfaVariableValue dfaVar) {
|
||||
public boolean isNotNull(DfaVariableValue dfaVar) {
|
||||
DfaConstValue dfaNull = myFactory.getConstFactory().getNull();
|
||||
int c1Index = getOrCreateEqClassIndex(dfaVar);
|
||||
int c2Index = getOrCreateEqClassIndex(dfaNull);
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.intellij.codeInspection.dataFlow.instructions.AssignInstruction;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -76,7 +77,29 @@ public class DfaUtil {
|
||||
final Collection<PsiExpression> expressions = value == null ? null : value.get(variable);
|
||||
return expressions == null ? Collections.<PsiExpression>emptyList() : expressions;
|
||||
}
|
||||
|
||||
|
||||
public static enum Nullness {
|
||||
NOT_NULL,NULL,UNKNOWN
|
||||
}
|
||||
// TRUE->not null, FALSE->null, null->unknown
|
||||
@NotNull
|
||||
public static Nullness checkNullness(@Nullable final PsiVariable variable, @Nullable final PsiElement context) {
|
||||
if (variable == null || context == null) return Nullness.UNKNOWN;
|
||||
|
||||
final PsiElement codeBlock = getEnclosingCodeBlock(variable, context);
|
||||
if (codeBlock == null) {
|
||||
return Nullness.UNKNOWN;
|
||||
}
|
||||
final ValuableInstructionVisitor visitor = new ValuableInstructionVisitor(context);
|
||||
RunnerResult result = new ValuableDataFlowRunner().analyzeMethod(codeBlock, visitor);
|
||||
if (result != RunnerResult.OK) {
|
||||
return Nullness.UNKNOWN;
|
||||
}
|
||||
if (visitor.myNulls.contains(variable)) return Nullness.NULL;
|
||||
if (visitor.myNotNulls.contains(variable)) return Nullness.NOT_NULL;
|
||||
return Nullness.UNKNOWN;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiCodeBlock getTopmostBlockInSameClass(@NotNull PsiElement position) {
|
||||
PsiCodeBlock block = PsiTreeUtil.getParentOfType(position, PsiCodeBlock.class, false, PsiMember.class, PsiFile.class);
|
||||
@@ -198,6 +221,8 @@ public class DfaUtil {
|
||||
|
||||
private static class ValuableInstructionVisitor extends StandardInstructionVisitor {
|
||||
final MultiValuesMap<PsiVariable, PsiExpression> myValues = new MultiValuesMap<PsiVariable, PsiExpression>(true);
|
||||
final Set<PsiVariable> myNulls = new THashSet<PsiVariable>();
|
||||
final Set<PsiVariable> myNotNulls = new THashSet<PsiVariable>();
|
||||
private final PsiElement myContext;
|
||||
|
||||
public ValuableInstructionVisitor(PsiElement context) {
|
||||
@@ -216,6 +241,15 @@ public class DfaUtil {
|
||||
myValues.put(variableValue.getPsiVariable(), psiExpression);
|
||||
}
|
||||
}
|
||||
DfaValue value = instruction.getValue();
|
||||
if (value instanceof DfaVariableValue) {
|
||||
if (memState.isNotNull((DfaVariableValue)value)) {
|
||||
myNotNulls.add(((DfaVariableValue)value).getPsiVariable());
|
||||
}
|
||||
if (memState.isNull(value)) {
|
||||
myNulls.add(((DfaVariableValue)value).getPsiVariable());
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visitPush(instruction, runner, memState);
|
||||
}
|
||||
|
||||
+3
-1
@@ -87,13 +87,15 @@ public class UnusedLibrariesInspection extends DescriptorProviderInspection {
|
||||
});
|
||||
libraryRoots.addAll(Arrays.asList(LibraryUtil.getLibraryRoots(modules.toArray(new Module[modules.size()]), false, false)));
|
||||
}
|
||||
GlobalSearchScope searchScope = null;
|
||||
GlobalSearchScope searchScope;
|
||||
try {
|
||||
@NonNls final String libsName = "libs";
|
||||
searchScope = GlobalSearchScope.filterScope(project, new NamedScope(libsName, PackageSetFactory.getInstance().compile("lib:*..*")));
|
||||
}
|
||||
catch (ParsingException e) {
|
||||
//can't be
|
||||
LOG.error(e);
|
||||
return;
|
||||
}
|
||||
final AnalysisScope analysisScope = new AnalysisScope(searchScope, project);
|
||||
analysisScope.setSearchInLibraries(true);
|
||||
|
||||
@@ -536,7 +536,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
|
||||
}
|
||||
|
||||
private void checkModifierListOwner(PsiElement child) {
|
||||
if (child instanceof PsiModifierListOwner) {
|
||||
if (child instanceof PsiClass || child instanceof PsiMethod) {
|
||||
PsiModifierList modifierList = ((PsiModifierListOwner)child).getModifierList();
|
||||
if (modifierList != null && modifierList.getAnnotations().length > 0) {
|
||||
myModificationTracker.incAnnotationModificationCounter();
|
||||
|
||||
+5
-1
@@ -29,7 +29,11 @@ public class MoveClassesHandler extends MoveClassesOrPackagesHandlerBase {
|
||||
for(PsiElement element: elements) {
|
||||
PsiFile parentFile;
|
||||
if (element instanceof PsiJavaFile) {
|
||||
if (((PsiJavaFile)element).getClasses().length == 0) return false;
|
||||
final PsiClass[] classes = ((PsiJavaFile)element).getClasses();
|
||||
if (classes.length == 0) return false;
|
||||
for (PsiClass aClass : classes) {
|
||||
if (aClass instanceof JspClass) return false;
|
||||
}
|
||||
parentFile = (PsiFile)element;
|
||||
} else {
|
||||
if (element instanceof JspClass) return false;
|
||||
|
||||
+9
-1
@@ -388,12 +388,20 @@ public class MoveInstanceMethodProcessor extends BaseRefactoringProcessor{
|
||||
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
try {
|
||||
final PsiExpression qualifier = expression.getQualifierExpression();
|
||||
final PsiElement resolved = expression.resolve();
|
||||
if (qualifier instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifier).isReferenceTo(myTargetVariable)) {
|
||||
if (resolved instanceof PsiField) {
|
||||
for (PsiParameter parameter : myMethod.getParameterList().getParameters()) {
|
||||
if (Comparing.strEqual(parameter.getName(), ((PsiField)resolved).getName())) {
|
||||
qualifier.replace(factory.createExpressionFromText("this", null));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Target is a field, replace target.m -> m
|
||||
qualifier.delete();
|
||||
return;
|
||||
}
|
||||
final PsiElement resolved = expression.resolve();
|
||||
if (myTargetVariable.equals(resolved)) {
|
||||
PsiThisExpression thisExpression = (PsiThisExpression)factory.createExpressionFromText("this", null);
|
||||
expression.replace(thisExpression);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
public class Test {
|
||||
|
||||
private Bar bar = new Bar();
|
||||
|
||||
public void <caret>foo(int x) {
|
||||
bar.x = x;
|
||||
}
|
||||
|
||||
private static class Bar {
|
||||
private int x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
public class Test {
|
||||
|
||||
private Bar bar = new Bar();
|
||||
|
||||
private static class Bar {
|
||||
private int x;
|
||||
|
||||
public void foo(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
public class Test {
|
||||
|
||||
private Bar bar = new Bar();
|
||||
|
||||
public void <caret>foo(int y) {
|
||||
bar.x = y;
|
||||
}
|
||||
|
||||
private static class Bar {
|
||||
private int x;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
public class Test {
|
||||
|
||||
private Bar bar = new Bar();
|
||||
|
||||
private static class Bar {
|
||||
private int x;
|
||||
|
||||
public void foo(int y) {
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -57,6 +57,14 @@ public class MoveInstanceMethodTest extends LightCodeInsightTestCase {
|
||||
doTest(true, 0);
|
||||
}
|
||||
|
||||
public void testQualifyFieldAccess() throws Exception {
|
||||
doTest(false, 0);
|
||||
}
|
||||
|
||||
public void testStripFieldQualifier() throws Exception {
|
||||
doTest(false, 0);
|
||||
}
|
||||
|
||||
private void doTest(boolean isTargetParameter, final int targetIndex) throws Exception {
|
||||
doTest(isTargetParameter, targetIndex, null);
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(qname)) {
|
||||
return AllClassesSearch.search(searchScope, baseClass.getProject(), parameters.getNameCondition()).forEach(new Processor<PsiClass>() {
|
||||
public boolean process(PsiClass aClass) {
|
||||
ProgressManager.getInstance().checkCanceled();
|
||||
ProgressManager.checkCanceled();
|
||||
return consumer.process(aClass);
|
||||
}
|
||||
});
|
||||
@@ -173,7 +173,7 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, Clas
|
||||
final Set<PsiClass> processed = new HashSet<PsiClass>();
|
||||
final Processor<PsiClass> processor = new Processor<PsiClass>() {
|
||||
public boolean process(final PsiClass candidate) {
|
||||
ProgressManager.getInstance().checkCanceled();
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
final Ref<Boolean> result = new Ref<Boolean>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#include "stdafx.h"
|
||||
#include "IdeaWin32.h"
|
||||
#include "jni_util.h"
|
||||
#include "windows.h"
|
||||
|
||||
jfieldID nameId;
|
||||
|
||||
HANDLE FindFileInner(JNIEnv *env, jstring path, LPWIN32_FIND_DATA lpData) {
|
||||
const jchar* str = env->GetStringChars(path, 0);
|
||||
HANDLE h = FindFirstFile((LPCWSTR)str, lpData);
|
||||
env->ReleaseStringChars(path, str);
|
||||
return h;
|
||||
}
|
||||
|
||||
bool CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
|
||||
jint count)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<count; i++) {
|
||||
jobject p = env->GetObjectArrayElement(src, i);
|
||||
env->SetObjectArrayElement(dst, i, p);
|
||||
env->DeleteLocalRef(p);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static LONGLONG
|
||||
fileTimeToInt64 (const FILETIME * time)
|
||||
{
|
||||
ULARGE_INTEGER _time;
|
||||
|
||||
_time.LowPart = time->dwLowDateTime;
|
||||
_time.HighPart = time->dwHighDateTime;
|
||||
|
||||
return _time.QuadPart;
|
||||
}
|
||||
|
||||
jfieldID nameID;
|
||||
jfieldID attributesID;
|
||||
jfieldID timestampID;
|
||||
|
||||
jobject CreateFileInfo(JNIEnv *env, LPWIN32_FIND_DATA lpData, jclass cls) {
|
||||
|
||||
jobject o = env->AllocObject(cls);
|
||||
if (o == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
jstring fileName = env->NewString((jchar*)lpData->cFileName, (jsize)wcslen(lpData->cFileName));
|
||||
if (fileName == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
env->SetObjectField(o, nameID, fileName);
|
||||
env->SetIntField(o, attributesID, lpData->dwFileAttributes);
|
||||
env->SetLongField(o, timestampID, fileTimeToInt64(&lpData->ftLastWriteTime));
|
||||
return o;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_intellij_openapi_vfs_impl_win32_FileInfo_initIDs(JNIEnv *env, jclass cls) {
|
||||
nameID = env->GetFieldID(cls, "name", "Ljava/lang/String;");
|
||||
attributesID = env->GetFieldID(cls, "attributes", "I");
|
||||
timestampID = env->GetFieldID(cls, "timestamp", "J");
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_getInfo(JNIEnv *env, jobject method, jstring path) {
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = FindFileInner(env, path, &data);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
}
|
||||
FindClose(h);
|
||||
jclass infoClass = env->FindClass("com/intellij/openapi/vfs/impl/win32/FileInfo");
|
||||
return CreateFileInfo(env, &data, infoClass);
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_listChildren(JNIEnv *env, jobject method, jstring path)
|
||||
{
|
||||
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = FindFileInner(env, path, &data);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jobjectArray rv, old;
|
||||
int len, maxlen;
|
||||
|
||||
len = 0;
|
||||
maxlen = 16;
|
||||
jclass infoClass = env->FindClass("com/intellij/openapi/vfs/impl/win32/FileInfo");
|
||||
rv = env->NewObjectArray(maxlen, infoClass, NULL);
|
||||
if (rv == NULL) goto error;
|
||||
do {
|
||||
if (len == maxlen) {
|
||||
old = rv;
|
||||
rv = env->NewObjectArray(maxlen <<= 1,
|
||||
infoClass, NULL);
|
||||
if (rv == NULL) goto error;
|
||||
if (!CopyObjectArray(env, rv, old, len)) goto error;
|
||||
env->DeleteLocalRef(old);
|
||||
}
|
||||
jobject o = CreateFileInfo(env, &data, infoClass);
|
||||
env->SetObjectArrayElement(rv, len++, o);
|
||||
env->DeleteLocalRef(o);
|
||||
}
|
||||
while (FindNextFile(h, &data));
|
||||
|
||||
FindClose(h);
|
||||
|
||||
old = rv;
|
||||
rv = env->NewObjectArray(len, infoClass, NULL);
|
||||
if (rv == NULL) goto error;
|
||||
if (!CopyObjectArray(env, rv, old, len)) goto error;
|
||||
return rv;
|
||||
|
||||
|
||||
error:
|
||||
FindClose(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "jni.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_intellij_openapi_vfs_impl_win32_FileInfo_initIDs(JNIEnv *env, jclass cls);
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_getInfo(JNIEnv *env, jobject method, jstring path);
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_listChildren(JNIEnv *env, jobject method, jstring path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="IdeaWin32"
|
||||
ProjectGUID="{D1A0CC4B-C100-46E4-918A-958626AE1ACF}"
|
||||
RootNamespace="IdeaWin32"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
DisableLanguageExtensions="false"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\IdeaWin32.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IdeaWin32.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\stdafx.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 1997 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
#ifndef _JLONG_H_
|
||||
#define _JLONG_H_
|
||||
|
||||
#include "jlong_md.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_JLONG_MD_H_
|
||||
#define _WIN32_JLONG_MD_H_
|
||||
|
||||
/* Make sure ptrdiff_t is defined */
|
||||
#include <stddef.h>
|
||||
|
||||
#define jlong_high(a) ((jint)((a)>>32))
|
||||
#define jlong_low(a) ((jint)(a))
|
||||
#define jlong_add(a, b) ((a) + (b))
|
||||
#define jlong_and(a, b) ((a) & (b))
|
||||
#define jlong_div(a, b) ((a) / (b))
|
||||
#define jlong_mul(a, b) ((a) * (b))
|
||||
#define jlong_neg(a) (-(a))
|
||||
#define jlong_not(a) (~(a))
|
||||
#define jlong_or(a, b) ((a) | (b))
|
||||
#define jlong_shl(a, n) ((a) << (n))
|
||||
#define jlong_shr(a, n) ((a) >> (n))
|
||||
#define jlong_sub(a, b) ((a) - (b))
|
||||
#define jlong_xor(a, b) ((a) ^ (b))
|
||||
#define jlong_rem(a,b) ((a) % (b))
|
||||
|
||||
/* comparison operators */
|
||||
#define jlong_ltz(ll) ((ll) < 0)
|
||||
#define jlong_gez(ll) ((ll) >= 0)
|
||||
#define jlong_gtz(ll) ((ll) > 0)
|
||||
#define jlong_eqz(a) ((a) == 0)
|
||||
#define jlong_eq(a, b) ((a) == (b))
|
||||
#define jlong_ne(a,b) ((a) != (b))
|
||||
#define jlong_ge(a,b) ((a) >= (b))
|
||||
#define jlong_le(a,b) ((a) <= (b))
|
||||
#define jlong_lt(a,b) ((a) < (b))
|
||||
#define jlong_gt(a,b) ((a) > (b))
|
||||
|
||||
#define jlong_zero ((jlong) 0)
|
||||
#define jlong_one ((jlong) 1)
|
||||
#define jlong_minus_one ((jlong) -1)
|
||||
|
||||
/* For static variables initialized to zero */
|
||||
#define jlong_zero_init ((jlong) 0)
|
||||
|
||||
#ifdef _WIN64
|
||||
#define jlong_to_ptr(a) ((void*)(a))
|
||||
#define ptr_to_jlong(a) ((jlong)(a))
|
||||
#else
|
||||
/* Double casting to avoid warning messages looking for casting of */
|
||||
/* smaller sizes into pointers */
|
||||
#define jlong_to_ptr(a) ((void*)(int)(a))
|
||||
#define ptr_to_jlong(a) ((jlong)(int)(a))
|
||||
#endif
|
||||
|
||||
#define jint_to_jlong(a) ((jlong)(a))
|
||||
#define jlong_to_jint(a) ((jint)(a))
|
||||
|
||||
/* Useful on machines where jlong and jdouble have different endianness. */
|
||||
#define jlong_to_jdouble_bits(a)
|
||||
#define jdouble_to_jlong_bits(a)
|
||||
|
||||
#define jlong_to_int(a) ((int)(a))
|
||||
#define int_to_jlong(a) ((jlong)(a))
|
||||
#define jlong_to_uint(a) ((unsigned int)(a))
|
||||
#define uint_to_jlong(a) ((jlong)(a))
|
||||
#define jlong_to_ptrdiff(a) ((ptrdiff_t)(a))
|
||||
#define ptrdiff_to_jlong(a) ((jlong)(a))
|
||||
#define jlong_to_size(a) ((size_t)(a))
|
||||
#define size_to_jlong(a) ((jlong)(a))
|
||||
#define long_to_jlong(a) ((jlong)(a))
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @(#)jni_md.h 1.15 05/11/17
|
||||
*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _JAVASOFT_JNI_MD_H_
|
||||
#define _JAVASOFT_JNI_MD_H_
|
||||
|
||||
#define JNIEXPORT __declspec(dllexport)
|
||||
#define JNIIMPORT __declspec(dllimport)
|
||||
#define JNICALL __stdcall
|
||||
|
||||
typedef long jint;
|
||||
typedef __int64 jlong;
|
||||
typedef signed char jbyte;
|
||||
|
||||
#endif /* !_JAVASOFT_JNI_MD_H_ */
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
#ifndef JNI_UTIL_H
|
||||
#define JNI_UTIL_H
|
||||
|
||||
#include "jni.h"
|
||||
#include "jlong.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file contains utility functions that can be implemented in pure JNI.
|
||||
*
|
||||
* Caution: Callers of functions declared in this file should be
|
||||
* particularly aware of the fact that these functions are convenience
|
||||
* functions, and as such are often compound operations, each one of
|
||||
* which may throw an exception. Therefore, the functions this file
|
||||
* will often return silently if an exception has occured, and callers
|
||||
* must check for exception themselves.
|
||||
*/
|
||||
|
||||
/* Throw a Java exception by name. Similar to SignalError. */
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg);
|
||||
|
||||
/* Throw common exceptions */
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowNullPointerException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowInternalError(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowIOException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowInstantiationException(JNIEnv *env, const char *msg);
|
||||
|
||||
/* Throw an exception by name, using the string returned by
|
||||
* JVM_LastErrorString for the detail string. If the last-error
|
||||
* string is NULL, use the given default detail string.
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
|
||||
const char *defaultMessage);
|
||||
|
||||
/* Throw an IOException, using the last-error string for the detail
|
||||
* string. If the last-error string is NULL, use the given default
|
||||
* detail string.
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail);
|
||||
|
||||
/* Convert between Java strings and i18n C strings */
|
||||
JNIEXPORT jstring
|
||||
NewStringPlatform(JNIEnv *env, const char *str);
|
||||
|
||||
JNIEXPORT const char *
|
||||
GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
JNU_NewStringPlatform(JNIEnv *env, const char *str);
|
||||
|
||||
JNIEXPORT const char * JNICALL
|
||||
JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str);
|
||||
|
||||
/* Class constants */
|
||||
JNIEXPORT jclass JNICALL
|
||||
JNU_ClassString(JNIEnv *env);
|
||||
|
||||
JNIEXPORT jclass JNICALL
|
||||
JNU_ClassClass(JNIEnv *env);
|
||||
|
||||
JNIEXPORT jclass JNICALL
|
||||
JNU_ClassObject(JNIEnv *env);
|
||||
|
||||
JNIEXPORT jclass JNICALL
|
||||
JNU_ClassThrowable(JNIEnv *env);
|
||||
|
||||
/* Copy count number of arguments from src to dst. Array bounds
|
||||
* and ArrayStoreException are checked.
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
|
||||
jint count);
|
||||
|
||||
/* Invoke a object-returning static method, based on class name,
|
||||
* method name, and signature string.
|
||||
*
|
||||
* The caller should check for exceptions by setting hasException
|
||||
* argument. If the caller is not interested in whether an exception
|
||||
* has occurred, pass in NULL.
|
||||
*/
|
||||
JNIEXPORT jvalue JNICALL
|
||||
JNU_CallStaticMethodByName(JNIEnv *env,
|
||||
jboolean *hasException,
|
||||
const char *class_name,
|
||||
const char *name,
|
||||
const char *signature,
|
||||
...);
|
||||
|
||||
/* Invoke an instance method by name.
|
||||
*/
|
||||
JNIEXPORT jvalue JNICALL
|
||||
JNU_CallMethodByName(JNIEnv *env,
|
||||
jboolean *hasException,
|
||||
jobject obj,
|
||||
const char *name,
|
||||
const char *signature,
|
||||
...);
|
||||
|
||||
JNIEXPORT jvalue JNICALL
|
||||
JNU_CallMethodByNameV(JNIEnv *env,
|
||||
jboolean *hasException,
|
||||
jobject obj,
|
||||
const char *name,
|
||||
const char *signature,
|
||||
va_list args);
|
||||
|
||||
/* Construct a new object of class, specifying the class by name,
|
||||
* and specififying which constructor to run and what arguments to
|
||||
* pass to it.
|
||||
*
|
||||
* The method will return an initialized instance if successful.
|
||||
* It will return NULL if an error has occured (for example if
|
||||
* it ran out of memory) and the appropriate Java exception will
|
||||
* have been thrown.
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL
|
||||
JNU_NewObjectByName(JNIEnv *env, const char *class_name,
|
||||
const char *constructor_sig, ...);
|
||||
|
||||
/* returns:
|
||||
* 0: object is not an instance of the class named by classname.
|
||||
* 1: object is an instance of the class named by classname.
|
||||
* -1: the class named by classname cannot be found. An exception
|
||||
* has been thrown.
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char *classname);
|
||||
|
||||
|
||||
/* Get or set class and instance fields.
|
||||
* Note that set functions take a variable number of arguments,
|
||||
* but only one argument of the appropriate type can be passed.
|
||||
* For example, to set an integer field i to 100:
|
||||
*
|
||||
* JNU_SetFieldByName(env, &exc, obj, "i", "I", 100);
|
||||
*
|
||||
* To set a float field f to 12.3:
|
||||
*
|
||||
* JNU_SetFieldByName(env, &exc, obj, "f", "F", 12.3);
|
||||
*
|
||||
* The caller should check for exceptions by setting hasException
|
||||
* argument. If the caller is not interested in whether an exception
|
||||
* has occurred, pass in NULL.
|
||||
*/
|
||||
JNIEXPORT jvalue JNICALL
|
||||
JNU_GetFieldByName(JNIEnv *env,
|
||||
jboolean *hasException,
|
||||
jobject obj,
|
||||
const char *name,
|
||||
const char *sig);
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_SetFieldByName(JNIEnv *env,
|
||||
jboolean *hasException,
|
||||
jobject obj,
|
||||
const char *name,
|
||||
const char *sig,
|
||||
...);
|
||||
|
||||
JNIEXPORT jvalue JNICALL
|
||||
JNU_GetStaticFieldByName(JNIEnv *env,
|
||||
jboolean *hasException,
|
||||
const char *classname,
|
||||
const char *name,
|
||||
const char *sig);
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_SetStaticFieldByName(JNIEnv *env,
|
||||
jboolean *hasException,
|
||||
const char *classname,
|
||||
const char *name,
|
||||
const char *sig,
|
||||
...);
|
||||
|
||||
|
||||
/*
|
||||
* Calls the .equals method.
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
JNU_Equals(JNIEnv *env, jobject object1, jobject object2);
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Thread calls
|
||||
*
|
||||
* Convenience thread-related calls on the java.lang.Object class.
|
||||
*/
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_Notify(JNIEnv *env, jobject object);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_NotifyAll(JNIEnv *env, jobject object);
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Miscellaneous utilities used by the class libraries
|
||||
*/
|
||||
|
||||
#define IS_NULL(obj) ((obj) == NULL)
|
||||
#define JNU_IsNull(env,obj) ((obj) == NULL)
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Debugging utilities
|
||||
*/
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_PrintString(JNIEnv *env, char *hdr, jstring string);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNU_PrintClass(JNIEnv *env, char *hdr, jobject object);
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
JNU_ToString(JNIEnv *env, jobject object);
|
||||
|
||||
/*
|
||||
* Package shorthand for use by native libraries
|
||||
*/
|
||||
#define JNU_JAVAPKG "java/lang/"
|
||||
#define JNU_JAVAIOPKG "java/io/"
|
||||
#define JNU_JAVANETPKG "java/net/"
|
||||
|
||||
/*
|
||||
* Check if the current thread is attached to the VM, and returns
|
||||
* the JNIEnv of the specified version if the thread is attached.
|
||||
*
|
||||
* If the current thread is not attached, this function returns 0.
|
||||
*
|
||||
* If the current thread is attached, this function returns the
|
||||
* JNI environment, or returns (void *)JNI_ERR if the specified
|
||||
* version is not supported.
|
||||
*/
|
||||
JNIEXPORT void * JNICALL
|
||||
JNU_GetEnv(JavaVM *vm, jint version);
|
||||
|
||||
/*
|
||||
* Warning free access to pointers stored in Java long fields.
|
||||
*/
|
||||
#define JNU_GetLongFieldAsPtr(env,obj,id) \
|
||||
(jlong_to_ptr((*(env))->GetLongField((env),(obj),(id))))
|
||||
#define JNU_SetLongFieldFromPtr(env,obj,id,val) \
|
||||
(*(env))->SetLongField((env),(obj),(id),ptr_to_jlong(val))
|
||||
|
||||
/*
|
||||
* Internal use only.
|
||||
*/
|
||||
enum {
|
||||
NO_ENCODING_YET = 0, /* "sun.jnu.encoding" not yet set */
|
||||
NO_FAST_ENCODING, /* Platform encoding is not fast */
|
||||
FAST_8859_1, /* ISO-8859-1 */
|
||||
FAST_CP1252, /* MS-DOS Cp1252 */
|
||||
FAST_646_US /* US-ASCII : ISO646-US */
|
||||
};
|
||||
|
||||
jstring nativeNewStringPlatform(JNIEnv *env, const char *str);
|
||||
|
||||
char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
|
||||
|
||||
int getFastEncoding();
|
||||
|
||||
void initializeEncoding();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* JNI_UTIL_H */
|
||||
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// IdeaWin32.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -0,0 +1,28 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
// Modify the following defines if you have to target a platform prior to the ones specified below.
|
||||
// Refer to MSDN for the latest info on corresponding values for different platforms.
|
||||
#ifndef WINVER // Allow use of features specific to Windows XP or later.
|
||||
#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
|
||||
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
|
||||
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
|
||||
#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
|
||||
#endif
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
@@ -131,6 +131,7 @@ public class AnalysisScope {
|
||||
myModules = null;
|
||||
myScope = scope;
|
||||
myType = CUSTOM;
|
||||
mySearchInLibraries = scope instanceof GlobalSearchScope && ((GlobalSearchScope)scope).isSearchInLibraries();
|
||||
}
|
||||
|
||||
public AnalysisScope(@NotNull Project project, @NotNull Collection<VirtualFile> virtualFiles) {
|
||||
@@ -198,6 +199,11 @@ public class AnalysisScope {
|
||||
|
||||
public boolean contains(VirtualFile file) {
|
||||
if (myFilesSet == null) {
|
||||
if (myType == CUSTOM) {
|
||||
// optimization
|
||||
if (myScope instanceof GlobalSearchScope) return ((GlobalSearchScope)myScope).contains(file);
|
||||
if (myScope instanceof LocalSearchScope) return ((LocalSearchScope)myScope).isInScope(file);
|
||||
}
|
||||
if (myType == PROJECT) { //optimization
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
return index.isInContent(file) && (myIncludeTestSource || !index.isInTestSourceContent(file));
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.intention;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.CustomLoadingExtensionPointBean;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -29,7 +30,7 @@ import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class IntentionActionBean extends CustomLoadingExtensionPointBean {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.IntentionActionBean");
|
||||
@Tag("className")
|
||||
public String className;
|
||||
@Tag("category")
|
||||
@@ -45,6 +46,9 @@ public class IntentionActionBean extends CustomLoadingExtensionPointBean {
|
||||
public String[] getCategories() {
|
||||
if (categoryKey != null) {
|
||||
final String baseName = bundleName != null ? bundleName : ((IdeaPluginDescriptor)myPluginDescriptor).getResourceBundleBaseName();
|
||||
if (baseName == null) {
|
||||
LOG.error("No resource bundle specified for "+myPluginDescriptor);
|
||||
}
|
||||
final ResourceBundle bundle = ResourceBundle.getBundle(baseName, Locale.getDefault(), myPluginDescriptor.getPluginClassLoader());
|
||||
|
||||
final String[] keys = categoryKey.split("/");
|
||||
|
||||
@@ -54,7 +54,7 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
public boolean FILTER_RESOLVED_ITEMS = true;
|
||||
public boolean ANALYZE_TEST_SOURCES = true;
|
||||
public boolean SHOW_DIFF_WITH_PREVIOUS_RUN = false;
|
||||
public int SCOPE_TYPE = 1;
|
||||
public int SCOPE_TYPE = AnalysisScope.PROJECT;
|
||||
public String CUSTOM_SCOPE_NAME = "";
|
||||
private final AutoScrollToSourceHandler myAutoScrollToSourceHandler;
|
||||
public boolean SHOW_ONLY_DIFF = false;
|
||||
|
||||
@@ -143,7 +143,6 @@ public class BaseAnalysisActionDialog extends DialogWrapper {
|
||||
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
boolean searchInLib = file != null && (fileIndex.isInLibraryClasses(file) || fileIndex.isInLibrarySource(file));
|
||||
|
||||
|
||||
String preselect = StringUtil.isEmptyOrSpaces(myAnalysisOptions.CUSTOM_SCOPE_NAME)
|
||||
? FindSettings.getInstance().getDefaultScopeName()
|
||||
: myAnalysisOptions.CUSTOM_SCOPE_NAME;
|
||||
@@ -153,6 +152,7 @@ public class BaseAnalysisActionDialog extends DialogWrapper {
|
||||
if (GlobalSearchScope.allScope(myProject).getDisplayName().equals(preselect)) {
|
||||
myAnalysisOptions.SCOPE_TYPE = AnalysisScope.CUSTOM;
|
||||
myAnalysisOptions.CUSTOM_SCOPE_NAME = preselect;
|
||||
searchInLib = true;
|
||||
}
|
||||
|
||||
//custom scope
|
||||
@@ -217,11 +217,6 @@ public class BaseAnalysisActionDialog extends DialogWrapper {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void doOKAction() {
|
||||
myAnalysisOptions.CUSTOM_SCOPE_NAME = myScopeCombo.getSelectedScopeName();
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
public boolean isInspectTestSources(){
|
||||
return myInspectTestSource.isSelected();
|
||||
}
|
||||
@@ -276,6 +271,8 @@ public class BaseAnalysisActionDialog extends DialogWrapper {
|
||||
}
|
||||
uiOptions.ANALYZE_TEST_SOURCES = isInspectTestSources();
|
||||
scope.setIncludeTestSource(isInspectTestSources());
|
||||
|
||||
FindSettings.getInstance().setDefaultScopeName(scope.getDisplayName());
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
|
||||
+77
-39
@@ -1,24 +1,24 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
* 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.codeInsight.template.impl;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightActionHandler;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
@@ -35,8 +35,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ListTemplatesHandler implements CodeInsightActionHandler{
|
||||
public class ListTemplatesHandler implements CodeInsightActionHandler {
|
||||
public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
|
||||
if (!file.isWritable()) return;
|
||||
EditorUtil.fillVirtualSpaceUntilCaret(editor);
|
||||
@@ -51,11 +52,11 @@ public class ListTemplatesHandler implements CodeInsightActionHandler{
|
||||
matchingTemplates.add(template);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (matchingTemplates.size() == 0) {
|
||||
String text = prefix.length() == 0
|
||||
? CodeInsightBundle.message("templates.no.defined")
|
||||
: CodeInsightBundle.message("templates.no.defined.with.prefix", prefix);
|
||||
? CodeInsightBundle.message("templates.no.defined")
|
||||
: CodeInsightBundle.message("templates.no.defined.with.prefix", prefix);
|
||||
HintManager.getInstance().showErrorHint(editor, text);
|
||||
return;
|
||||
}
|
||||
@@ -65,27 +66,42 @@ public class ListTemplatesHandler implements CodeInsightActionHandler{
|
||||
|
||||
public static void showTemplatesLookup(final Project project, final Editor editor, String prefix, List<TemplateImpl> matchingTemplates) {
|
||||
ArrayList<LookupItem> array = new ArrayList<LookupItem>();
|
||||
for (TemplateImpl template: matchingTemplates) {
|
||||
for (TemplateImpl template : matchingTemplates) {
|
||||
array.add(new LookupItem(template, template.getKey()));
|
||||
}
|
||||
LookupElement[] items = array.toArray(new LookupElement[array.size()]);
|
||||
|
||||
final LookupImpl lookup = (LookupImpl) LookupManager.getInstance(project).createLookup(editor, items, prefix, LookupArranger.DEFAULT);
|
||||
lookup.addLookupListener(
|
||||
new LookupAdapter() {
|
||||
public void itemSelected(LookupEvent event) {
|
||||
final LookupElement lookupElement = event.getItem();
|
||||
if (lookupElement != null) {
|
||||
final TemplateImpl template = (TemplateImpl)lookupElement.getObject();
|
||||
new WriteCommandAction(project) {
|
||||
protected void run(Result result) throws Throwable {
|
||||
((TemplateManagerImpl) TemplateManager.getInstance(project)).startTemplateWithPrefix(editor, template, null);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
final LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, items, prefix, LookupArranger.DEFAULT);
|
||||
lookup.addLookupListener(new MyLookupAdapter(project, editor, null));
|
||||
lookup.show();
|
||||
}
|
||||
|
||||
private static String computePrefix(TemplateImpl template, String argument) {
|
||||
String key = template.getKey();
|
||||
if (argument == null) {
|
||||
return key;
|
||||
}
|
||||
if (key.length() > 0 && Character.isJavaIdentifierPart(key.charAt(key.length() - 1))) {
|
||||
return key + ' ' + argument;
|
||||
}
|
||||
return key + argument;
|
||||
}
|
||||
|
||||
public static void showTemplatesLookup(final Project project,
|
||||
final Editor editor,
|
||||
Map<TemplateImpl, String> template2Argument) {
|
||||
ArrayList<LookupItem> array = new ArrayList<LookupItem>();
|
||||
for (TemplateImpl template : template2Argument.keySet()) {
|
||||
String argument = template2Argument.get(template);
|
||||
String prefix = computePrefix(template, argument);
|
||||
LookupItem item = new LookupItem(template, prefix);
|
||||
item.setPrefixMatcher(new CamelHumpMatcher(prefix));
|
||||
array.add(item);
|
||||
}
|
||||
LookupElement[] items = array.toArray(new LookupElement[array.size()]);
|
||||
|
||||
final LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, items, null, LookupArranger.DEFAULT);
|
||||
lookup.addLookupListener(new MyLookupAdapter(project, editor, template2Argument));
|
||||
lookup.show();
|
||||
}
|
||||
|
||||
@@ -93,10 +109,10 @@ public class ListTemplatesHandler implements CodeInsightActionHandler{
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String getPrefix(Document document, int offset) {
|
||||
private String getPrefix(Document document, int offset) {
|
||||
CharSequence chars = document.getCharsSequence();
|
||||
int start = offset;
|
||||
while(true){
|
||||
while (true) {
|
||||
if (start == 0) break;
|
||||
char c = chars.charAt(start - 1);
|
||||
if (!isInPrefix(c)) break;
|
||||
@@ -105,7 +121,29 @@ public class ListTemplatesHandler implements CodeInsightActionHandler{
|
||||
return chars.subSequence(start, offset).toString();
|
||||
}
|
||||
|
||||
private static boolean isInPrefix(final char c) {
|
||||
private boolean isInPrefix(final char c) {
|
||||
return Character.isJavaIdentifierPart(c) || c == '.';
|
||||
}
|
||||
|
||||
private static class MyLookupAdapter extends LookupAdapter {
|
||||
private final Project myProject;
|
||||
private final Editor myEditor;
|
||||
private final Map<TemplateImpl, String> myTemplate2Argument;
|
||||
|
||||
public MyLookupAdapter(Project project, Editor editor, Map<TemplateImpl, String> template2Argument) {
|
||||
myProject = project;
|
||||
myEditor = editor;
|
||||
myTemplate2Argument = template2Argument;
|
||||
}
|
||||
|
||||
public void itemSelected(LookupEvent event) {
|
||||
final TemplateImpl template = (TemplateImpl)event.getItem().getObject();
|
||||
final String argument = myTemplate2Argument != null ? myTemplate2Argument.get(template) : null;
|
||||
new WriteCommandAction(myProject) {
|
||||
protected void run(Result result) throws Throwable {
|
||||
((TemplateManagerImpl)TemplateManager.getInstance(myProject)).startTemplateWithPrefix(myEditor, template, null, argument);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ public class TemplateImpl extends Template implements SchemeElement {
|
||||
@NonNls public static final String SELECTION = "SELECTION";
|
||||
@NonNls public static final String SELECTION_START = "SELECTION_START";
|
||||
@NonNls public static final String SELECTION_END = "SELECTION_END";
|
||||
@NonNls public static final String ARG = "ARG";
|
||||
|
||||
public static final Set<String> INTERNAL_VARS_SET = new HashSet<String>(Arrays.asList(
|
||||
END, SELECTION, SELECTION_START, SELECTION_END));
|
||||
@@ -381,6 +382,13 @@ public class TemplateImpl extends Template implements SchemeElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasArgument() {
|
||||
for (Variable v : myVariables) {
|
||||
if (v.getName().equals(ARG)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setId(final String id) {
|
||||
myId = id;
|
||||
}
|
||||
|
||||
+141
-72
@@ -36,6 +36,7 @@ import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -59,7 +60,8 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
myDisposables.clear();
|
||||
}
|
||||
|
||||
public void initComponent() { }
|
||||
public void initComponent() {
|
||||
}
|
||||
|
||||
public void projectClosed() {
|
||||
}
|
||||
@@ -133,12 +135,17 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
startTemplate(editor, selectionString, template, null, null);
|
||||
}
|
||||
|
||||
public void startTemplate(@NotNull Editor editor, @NotNull Template template, TemplateEditingListener listener,
|
||||
public void startTemplate(@NotNull Editor editor,
|
||||
@NotNull Template template,
|
||||
TemplateEditingListener listener,
|
||||
final PairProcessor<String, String> processor) {
|
||||
startTemplate(editor, null, template, listener, processor);
|
||||
}
|
||||
|
||||
private void startTemplate(final Editor editor, final String selectionString, final Template template, TemplateEditingListener listener,
|
||||
private void startTemplate(final Editor editor,
|
||||
final String selectionString,
|
||||
final Template template,
|
||||
TemplateEditingListener listener,
|
||||
final PairProcessor<String, String> processor) {
|
||||
final TemplateState templateState = initTemplateState(editor);
|
||||
|
||||
@@ -147,23 +154,21 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
if (listener != null) {
|
||||
templateState.addTemplateStateListener(listener);
|
||||
}
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
myProject, new Runnable() {
|
||||
public void run() {
|
||||
if (selectionString != null) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
EditorModificationUtil.deleteSelectedText(editor);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
editor.getSelectionModel().removeSelection();
|
||||
}
|
||||
templateState.start((TemplateImpl) template, processor);
|
||||
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
|
||||
public void run() {
|
||||
if (selectionString != null) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
EditorModificationUtil.deleteSelectedText(editor);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
CodeInsightBundle.message("insert.code.template.command"), null
|
||||
);
|
||||
else {
|
||||
editor.getSelectionModel().removeSelection();
|
||||
}
|
||||
templateState.start((TemplateImpl)template, processor, null);
|
||||
}
|
||||
}, CodeInsightBundle.message("insert.code.template.command"), null);
|
||||
|
||||
if (shouldSkipInTests()) {
|
||||
if (!templateState.isFinished()) templateState.gotoEnd();
|
||||
@@ -178,6 +183,23 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
startTemplate(editor, null, template, listener, null);
|
||||
}
|
||||
|
||||
private static int passArgumentBack(CharSequence text, int caretOffset) {
|
||||
int i = caretOffset - 1;
|
||||
for (; i >= 0; i--) {
|
||||
char c = text.charAt(i);
|
||||
if (!Character.isJavaIdentifierPart(c)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
private static <T, U> void addToMap(@NotNull Map<T, U> map, @NotNull Collection<? extends T> keys, U value) {
|
||||
for (T key : keys) {
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean startTemplate(final Editor editor, char shortcutChar, final PairProcessor<String, String> processor) {
|
||||
final Document document = editor.getDocument();
|
||||
PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, myProject);
|
||||
@@ -185,10 +207,69 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
|
||||
TemplateSettings templateSettings = TemplateSettings.getInstance();
|
||||
CharSequence text = document.getCharsSequence();
|
||||
|
||||
final int caretOffset = editor.getCaretModel().getOffset();
|
||||
String key = null;
|
||||
List<TemplateImpl> candidatesWithoutArgument = findMatchingTemplates(text, caretOffset, shortcutChar, templateSettings, false);
|
||||
|
||||
int argumentOffset = passArgumentBack(text, caretOffset);
|
||||
String argument = null;
|
||||
if (argumentOffset >= 0) {
|
||||
argument = text.subSequence(argumentOffset, caretOffset).toString();
|
||||
if (argumentOffset > 0 && text.charAt(argumentOffset - 1) == ' ') {
|
||||
if (argumentOffset - 2 >= 0 && Character.isJavaIdentifierPart(text.charAt(argumentOffset - 2))) {
|
||||
argumentOffset--;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<TemplateImpl> candidatesWithArgument = findMatchingTemplates(text, argumentOffset, shortcutChar, templateSettings, true);
|
||||
|
||||
if (candidatesWithArgument.isEmpty() && candidatesWithoutArgument.isEmpty()) return false;
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
|
||||
public void run() {
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(document);
|
||||
}
|
||||
}, "", null);
|
||||
|
||||
candidatesWithoutArgument = filterApplicableCandidates(file, caretOffset, candidatesWithoutArgument);
|
||||
candidatesWithArgument = filterApplicableCandidates(file, argumentOffset, candidatesWithArgument);
|
||||
Map<TemplateImpl, String> candidate2Argument = new HashMap<TemplateImpl, String>();
|
||||
addToMap(candidate2Argument, candidatesWithoutArgument, null);
|
||||
addToMap(candidate2Argument, candidatesWithArgument, argument);
|
||||
|
||||
if (candidate2Argument.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), myProject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidate2Argument.size() == 1) {
|
||||
TemplateImpl template = candidate2Argument.keySet().iterator().next();
|
||||
if (candidatesWithoutArgument.size() == 1) {
|
||||
int templateStart = caretOffset - template.getKey().length();
|
||||
startTemplateWithPrefix(editor, template, templateStart, processor, null);
|
||||
}
|
||||
else {
|
||||
int templateStart = argumentOffset - template.getKey().length();
|
||||
startTemplateWithPrefix(editor, template, templateStart, processor, argument);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ListTemplatesHandler.showTemplatesLookup(myProject, editor, candidate2Argument);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<TemplateImpl> findMatchingTemplates(CharSequence text,
|
||||
int caretOffset,
|
||||
char shortcutChar,
|
||||
TemplateSettings settings,
|
||||
boolean hasArgument) {
|
||||
String key;
|
||||
List<TemplateImpl> candidates = Collections.emptyList();
|
||||
for (int i = templateSettings.getMaxKeyLength(); i >= 1 ; i--) {
|
||||
for (int i = settings.getMaxKeyLength(); i >= 1; i--) {
|
||||
int wordStart = caretOffset - i;
|
||||
if (wordStart < 0) {
|
||||
continue;
|
||||
@@ -200,63 +281,47 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
}
|
||||
}
|
||||
|
||||
candidates = templateSettings.collectMatchingCandidates(key, shortcutChar);
|
||||
candidates = settings.collectMatchingCandidates(key, shortcutChar, hasArgument);
|
||||
if (!candidates.isEmpty()) break;
|
||||
}
|
||||
|
||||
if (candidates.isEmpty()) return false;
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
myProject, new Runnable() {
|
||||
public void run() {
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(document);
|
||||
}
|
||||
},
|
||||
"", null
|
||||
);
|
||||
|
||||
candidates = filterApplicableCandidates(file, caretOffset - key.length(), candidates);
|
||||
if (candidates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), myProject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidates.size() == 1) {
|
||||
TemplateImpl template = candidates.get(0);
|
||||
startTemplateWithPrefix(editor, template, processor);
|
||||
}
|
||||
else {
|
||||
ListTemplatesHandler.showTemplatesLookup(myProject, editor, key, candidates);
|
||||
}
|
||||
|
||||
return true;
|
||||
return candidates;
|
||||
}
|
||||
|
||||
public void startTemplateWithPrefix(final Editor editor, final TemplateImpl template, @Nullable final PairProcessor<String, String> processor) {
|
||||
public void startTemplateWithPrefix(final Editor editor,
|
||||
final TemplateImpl template,
|
||||
@Nullable final PairProcessor<String, String> processor,
|
||||
@Nullable String argument) {
|
||||
final int caretOffset = editor.getCaretModel().getOffset();
|
||||
int startOffset = caretOffset - template.getKey().length();
|
||||
if (argument != null) {
|
||||
startOffset -= argument.length();
|
||||
}
|
||||
startTemplateWithPrefix(editor, template, startOffset, processor, argument);
|
||||
}
|
||||
|
||||
public void startTemplateWithPrefix(final Editor editor,
|
||||
final TemplateImpl template,
|
||||
final int templateStart,
|
||||
@Nullable final PairProcessor<String, String> processor,
|
||||
@Nullable final String argument) {
|
||||
final int caretOffset = editor.getCaretModel().getOffset();
|
||||
final int wordStart = caretOffset - template.getKey().length();
|
||||
final TemplateState templateState = initTemplateState(editor);
|
||||
CommandProcessor commandProcessor = CommandProcessor.getInstance();
|
||||
commandProcessor.executeCommand(
|
||||
myProject, new Runnable() {
|
||||
public void run() {
|
||||
editor.getDocument().deleteString(wordStart, caretOffset);
|
||||
editor.getCaretModel().moveToOffset(wordStart);
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
editor.getSelectionModel().removeSelection();
|
||||
templateState.start(template, processor);
|
||||
}
|
||||
},
|
||||
CodeInsightBundle.message("insert.code.template.command"), null
|
||||
);
|
||||
commandProcessor.executeCommand(myProject, new Runnable() {
|
||||
public void run() {
|
||||
editor.getDocument().deleteString(templateStart, caretOffset);
|
||||
editor.getCaretModel().moveToOffset(templateStart);
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
editor.getSelectionModel().removeSelection();
|
||||
templateState.start(template, processor, argument);
|
||||
}
|
||||
}, CodeInsightBundle.message("insert.code.template.command"), null);
|
||||
}
|
||||
|
||||
private static List<TemplateImpl> filterApplicableCandidates(PsiFile file, int offset, List<TemplateImpl> candidates) {
|
||||
private static List<TemplateImpl> filterApplicableCandidates(PsiFile file, int caretOffset, List<TemplateImpl> candidates) {
|
||||
List<TemplateImpl> result = new ArrayList<TemplateImpl>();
|
||||
for (TemplateImpl candidate : candidates) {
|
||||
if (isApplicable(file, offset, candidate)) {
|
||||
if (isApplicable(file, caretOffset - candidate.getKey().length(), candidate)) {
|
||||
result.add(candidate);
|
||||
}
|
||||
}
|
||||
@@ -266,16 +331,20 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
public TemplateContextType getContextType(@NotNull PsiFile file, int offset) {
|
||||
final TemplateContextType[] typeCollection = getAllContextTypes();
|
||||
LinkedList<TemplateContextType> userDefinedExtensionsFirst = new LinkedList<TemplateContextType>();
|
||||
for(TemplateContextType contextType: typeCollection) {
|
||||
if (contextType.getClass().getName().startsWith("com.intellij.codeInsight.template")) userDefinedExtensionsFirst.addLast(contextType);
|
||||
else userDefinedExtensionsFirst.addFirst(contextType);
|
||||
for (TemplateContextType contextType : typeCollection) {
|
||||
if (contextType.getClass().getName().startsWith("com.intellij.codeInsight.template")) {
|
||||
userDefinedExtensionsFirst.addLast(contextType);
|
||||
}
|
||||
else {
|
||||
userDefinedExtensionsFirst.addFirst(contextType);
|
||||
}
|
||||
}
|
||||
for(TemplateContextType contextType: userDefinedExtensionsFirst) {
|
||||
for (TemplateContextType contextType : userDefinedExtensionsFirst) {
|
||||
if (contextType.isInContext(file, offset)) {
|
||||
return contextType;
|
||||
}
|
||||
}
|
||||
assert false: "OtherContextType should match any context";
|
||||
assert false : "OtherContextType should match any context";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -673,7 +673,7 @@ public class TemplateSettings implements PersistentStateComponent<Element>, Expo
|
||||
return mySchemesManager.getAllSchemes();
|
||||
}
|
||||
|
||||
public List<TemplateImpl> collectMatchingCandidates(String key, char shortcutChar) {
|
||||
public List<TemplateImpl> collectMatchingCandidates(String key, char shortcutChar, boolean hasArgument) {
|
||||
final Collection<TemplateImpl> templates = getTemplates(key);
|
||||
List<TemplateImpl> candidates = new ArrayList<TemplateImpl>();
|
||||
for (TemplateImpl template : templates) {
|
||||
@@ -686,6 +686,9 @@ public class TemplateSettings implements PersistentStateComponent<Element>, Expo
|
||||
if (template.isSelectionTemplate()) {
|
||||
continue;
|
||||
}
|
||||
if (hasArgument && !template.hasArgument()) {
|
||||
continue;
|
||||
}
|
||||
candidates.add(template);
|
||||
}
|
||||
return candidates;
|
||||
|
||||
+120
-117
@@ -71,6 +71,7 @@ public class TemplateState implements Disposable {
|
||||
|
||||
private TemplateImpl myTemplate;
|
||||
private TemplateSegments mySegments = null;
|
||||
private String myArgument;
|
||||
|
||||
private RangeMarker myTemplateRange = null;
|
||||
private final ArrayList<RangeHighlighter> myTabStopHighlighters = new ArrayList<RangeHighlighter>();
|
||||
@@ -106,6 +107,7 @@ public class TemplateState implements Disposable {
|
||||
|
||||
myCommandListener = new CommandAdapter() {
|
||||
boolean started = false;
|
||||
|
||||
public void commandStarted(CommandEvent event) {
|
||||
if (myEditor != null) {
|
||||
final int offset = myEditor.getCaretModel().getOffset();
|
||||
@@ -170,6 +172,9 @@ public class TemplateState implements Disposable {
|
||||
if (variableName.equals(TemplateImpl.END)) {
|
||||
return new TextResult("");
|
||||
}
|
||||
if (variableName.equals(TemplateImpl.ARG) && myArgument != null) {
|
||||
return new TextResult(myArgument);
|
||||
}
|
||||
|
||||
CharSequence text = myDocument.getCharsSequence();
|
||||
int segmentNumber = myTemplate.getVariableSegmentNumber(variableName);
|
||||
@@ -230,45 +235,43 @@ public class TemplateState implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public void start(TemplateImpl template, @Nullable final PairProcessor<String, String> processor) {
|
||||
public void start(TemplateImpl template, @Nullable final PairProcessor<String, String> processor, @Nullable String argument) {
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
|
||||
myProcessor = processor;
|
||||
|
||||
final DocumentReference[] refs = myDocument == null
|
||||
? null
|
||||
: new DocumentReference[] {DocumentReferenceManager.getInstance().create(myDocument) };
|
||||
final DocumentReference[] refs =
|
||||
myDocument == null ? null : new DocumentReference[]{DocumentReferenceManager.getInstance().create(myDocument)};
|
||||
|
||||
UndoManager.getInstance(myProject).undoableActionPerformed(
|
||||
new UndoableAction() {
|
||||
public void undo() {
|
||||
if (myDocument != null) {
|
||||
fireTemplateCancelled();
|
||||
LookupManager.getInstance(myProject).hideActiveLookup();
|
||||
int oldVar = myCurrentVariableNumber;
|
||||
setCurrentVariableNumber(-1);
|
||||
currentVariableChanged(oldVar);
|
||||
}
|
||||
}
|
||||
|
||||
public void redo() {
|
||||
//TODO:
|
||||
// throw new UnexpectedUndoException("Not implemented");
|
||||
}
|
||||
|
||||
public DocumentReference[] getAffectedDocuments() {
|
||||
return refs;
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return false;
|
||||
UndoManager.getInstance(myProject).undoableActionPerformed(new UndoableAction() {
|
||||
public void undo() {
|
||||
if (myDocument != null) {
|
||||
fireTemplateCancelled();
|
||||
LookupManager.getInstance(myProject).hideActiveLookup();
|
||||
int oldVar = myCurrentVariableNumber;
|
||||
setCurrentVariableNumber(-1);
|
||||
currentVariableChanged(oldVar);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
public void redo() {
|
||||
//TODO:
|
||||
// throw new UnexpectedUndoException("Not implemented");
|
||||
}
|
||||
|
||||
public DocumentReference[] getAffectedDocuments() {
|
||||
return refs;
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
myTemplateIndented = false;
|
||||
myCurrentVariableNumber = -1;
|
||||
mySegments = new TemplateSegments(myEditor);
|
||||
myTemplate = template;
|
||||
myArgument = argument;
|
||||
|
||||
|
||||
if (template.isInline()) {
|
||||
@@ -297,39 +300,37 @@ public class TemplateState implements Disposable {
|
||||
}
|
||||
|
||||
private void preprocessTemplate(final PsiFile file, int caretOffset, final String textToInsert) {
|
||||
for(TemplatePreprocessor preprocessor: Extensions.getExtensions(TemplatePreprocessor.EP_NAME)) {
|
||||
for (TemplatePreprocessor preprocessor : Extensions.getExtensions(TemplatePreprocessor.EP_NAME)) {
|
||||
preprocessor.preprocessTemplate(myEditor, file, caretOffset, textToInsert, myTemplate.getTemplateText());
|
||||
}
|
||||
}
|
||||
|
||||
private void processAllExpressions(final TemplateImpl template) {
|
||||
ApplicationManager.getApplication().runWriteAction(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
if (!template.isInline()) myDocument.insertString(myTemplateRange.getStartOffset(), template.getTemplateText());
|
||||
for (int i = 0; i < template.getSegmentsCount(); i++) {
|
||||
int segmentOffset = myTemplateRange.getStartOffset() + template.getSegmentOffset(i);
|
||||
mySegments.addSegment(segmentOffset, segmentOffset);
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
if (!template.isInline()) myDocument.insertString(myTemplateRange.getStartOffset(), template.getTemplateText());
|
||||
for (int i = 0; i < template.getSegmentsCount(); i++) {
|
||||
int segmentOffset = myTemplateRange.getStartOffset() + template.getSegmentOffset(i);
|
||||
mySegments.addSegment(segmentOffset, segmentOffset);
|
||||
}
|
||||
|
||||
calcResults(false);
|
||||
calcResults(false); //Fixed SCR #[vk500] : all variables should be recalced twice on start.
|
||||
doReformat();
|
||||
calcResults(false);
|
||||
calcResults(false); //Fixed SCR #[vk500] : all variables should be recalced twice on start.
|
||||
doReformat();
|
||||
|
||||
int nextVariableNumber = getNextVariableNumber(-1);
|
||||
if (nextVariableNumber == -1) {
|
||||
finishTemplateEditing();
|
||||
}
|
||||
else {
|
||||
setCurrentVariableNumber(nextVariableNumber);
|
||||
initTabStopHighlighters();
|
||||
initListeners();
|
||||
focusCurrentExpression();
|
||||
currentVariableChanged(-1);
|
||||
}
|
||||
int nextVariableNumber = getNextVariableNumber(-1);
|
||||
if (nextVariableNumber == -1) {
|
||||
finishTemplateEditing();
|
||||
}
|
||||
else {
|
||||
setCurrentVariableNumber(nextVariableNumber);
|
||||
initTabStopHighlighters();
|
||||
initListeners();
|
||||
focusCurrentExpression();
|
||||
currentVariableChanged(-1);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void doReformat() {
|
||||
@@ -352,7 +353,7 @@ public class TemplateState implements Disposable {
|
||||
if (file != null) {
|
||||
IntArrayList indices = initEmptyVariables();
|
||||
mySegments.setSegmentsGreedy(false);
|
||||
for(TemplateOptionalProcessor processor: Extensions.getExtensions(TemplateOptionalProcessor.EP_NAME)) {
|
||||
for (TemplateOptionalProcessor processor : Extensions.getExtensions(TemplateOptionalProcessor.EP_NAME)) {
|
||||
processor.processText(myProject, myTemplate, myDocument, myTemplateRange, myEditor);
|
||||
}
|
||||
mySegments.setSegmentsGreedy(true);
|
||||
@@ -371,7 +372,8 @@ public class TemplateState implements Disposable {
|
||||
setCurrentVariableNumber(-1);
|
||||
currentVariableChanged(oldIndex);
|
||||
fireTemplateCancelled();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
calcResults(true);
|
||||
}
|
||||
myDocumentChanged = false;
|
||||
@@ -427,15 +429,16 @@ public class TemplateState implements Disposable {
|
||||
final String s = lookupItems[0].getLookupString();
|
||||
EditorModificationUtil.insertStringAtCaret(myEditor, s);
|
||||
itemSelected(lookupItems[0], psiFile, currentSegmentNumber, ' ', lookupItems);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
runLookup(currentSegmentNumber, lookupItems, psiFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Result result = expressionNode.calculateResult(context);
|
||||
if (result != null) {
|
||||
result.handleFocused(psiFile, myDocument,
|
||||
mySegments.getSegmentStart(currentSegmentNumber), mySegments.getSegmentEnd(currentSegmentNumber));
|
||||
result.handleFocused(psiFile, myDocument, mySegments.getSegmentStart(currentSegmentNumber),
|
||||
mySegments.getSegmentEnd(currentSegmentNumber));
|
||||
}
|
||||
}
|
||||
focusCurrentHighlighter(true);
|
||||
@@ -465,7 +468,11 @@ public class TemplateState implements Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private void itemSelected(final LookupElement item, final PsiFile psiFile, final int currentSegmentNumber, final char completionChar, LookupElement[] elements) {
|
||||
private void itemSelected(final LookupElement item,
|
||||
final PsiFile psiFile,
|
||||
final int currentSegmentNumber,
|
||||
final char completionChar,
|
||||
LookupElement[] elements) {
|
||||
if (item != null) {
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
|
||||
@@ -490,11 +497,13 @@ public class TemplateState implements Disposable {
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(myDocument);
|
||||
}
|
||||
|
||||
final TemplateLookupSelectionHandler handler = item instanceof LookupItem ? ((LookupItem<?>)item).getAttribute(TemplateLookupSelectionHandler.KEY_IN_LOOKUP_ITEM) : null;
|
||||
final TemplateLookupSelectionHandler handler =
|
||||
item instanceof LookupItem ? ((LookupItem<?>)item).getAttribute(TemplateLookupSelectionHandler.KEY_IN_LOOKUP_ITEM) : null;
|
||||
if (handler != null) {
|
||||
handler.itemSelected(item, psiFile, myDocument,
|
||||
mySegments.getSegmentStart(currentSegmentNumber), mySegments.getSegmentEnd(currentSegmentNumber));
|
||||
} else {
|
||||
handler.itemSelected(item, psiFile, myDocument, mySegments.getSegmentStart(currentSegmentNumber),
|
||||
mySegments.getSegmentEnd(currentSegmentNumber));
|
||||
}
|
||||
else {
|
||||
new WriteCommandAction(myProject) {
|
||||
protected void run(com.intellij.openapi.application.Result result) throws Throwable {
|
||||
item.handleInsert(context);
|
||||
@@ -533,45 +542,43 @@ public class TemplateState implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
BitSet calcedSegments = new BitSet();
|
||||
int maxAttempts = (myTemplate.getVariableCount()+1)*3;
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
BitSet calcedSegments = new BitSet();
|
||||
int maxAttempts = (myTemplate.getVariableCount() + 1) * 3;
|
||||
|
||||
do {
|
||||
maxAttempts--;
|
||||
calcedSegments.clear();
|
||||
for (int i = myCurrentVariableNumber + 1; i < myTemplate.getVariableCount(); i++) {
|
||||
String variableName = myTemplate.getVariableNameAt(i);
|
||||
int segmentNumber = myTemplate.getVariableSegmentNumber(variableName);
|
||||
if (segmentNumber < 0) continue;
|
||||
Expression expression = myTemplate.getExpressionAt(i);
|
||||
Expression defaultValue = myTemplate.getDefaultValueAt(i);
|
||||
String oldValue = getVariableValue(variableName).getText();
|
||||
recalcSegment(segmentNumber, isQuick, expression, defaultValue);
|
||||
final TextResult value = getVariableValue(variableName);
|
||||
assert value != null : "name=" + variableName + "\ntext=" + myTemplate.getTemplateText();
|
||||
String newValue = value.getText();
|
||||
if (!newValue.equals(oldValue)) {
|
||||
calcedSegments.set(segmentNumber);
|
||||
}
|
||||
do {
|
||||
maxAttempts--;
|
||||
calcedSegments.clear();
|
||||
for (int i = myCurrentVariableNumber + 1; i < myTemplate.getVariableCount(); i++) {
|
||||
String variableName = myTemplate.getVariableNameAt(i);
|
||||
int segmentNumber = myTemplate.getVariableSegmentNumber(variableName);
|
||||
if (segmentNumber < 0) continue;
|
||||
Expression expression = myTemplate.getExpressionAt(i);
|
||||
Expression defaultValue = myTemplate.getDefaultValueAt(i);
|
||||
String oldValue = getVariableValue(variableName).getText();
|
||||
recalcSegment(segmentNumber, isQuick, expression, defaultValue);
|
||||
final TextResult value = getVariableValue(variableName);
|
||||
assert value != null : "name=" + variableName + "\ntext=" + myTemplate.getTemplateText();
|
||||
String newValue = value.getText();
|
||||
if (!newValue.equals(oldValue)) {
|
||||
calcedSegments.set(segmentNumber);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < myTemplate.getSegmentsCount(); i++) {
|
||||
if (!calcedSegments.get(i)) {
|
||||
String variableName = myTemplate.getSegmentName(i);
|
||||
String newValue = getVariableValue(variableName).getText();
|
||||
int start = mySegments.getSegmentStart(i);
|
||||
int end = mySegments.getSegmentEnd(i);
|
||||
replaceString(newValue, start, end, i);
|
||||
}
|
||||
for (int i = 0; i < myTemplate.getSegmentsCount(); i++) {
|
||||
if (!calcedSegments.get(i)) {
|
||||
String variableName = myTemplate.getSegmentName(i);
|
||||
String newValue = getVariableValue(variableName).getText();
|
||||
int start = mySegments.getSegmentStart(i);
|
||||
int end = mySegments.getSegmentEnd(i);
|
||||
replaceString(newValue, start, end, i);
|
||||
}
|
||||
}
|
||||
while (!calcedSegments.isEmpty() && maxAttempts >= 0);
|
||||
}
|
||||
while (!calcedSegments.isEmpty() && maxAttempts >= 0);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void recalcSegment(int segmentNumber, boolean isQuick, Expression expressionNode, Expression defaultValue) {
|
||||
@@ -615,8 +622,8 @@ public class TemplateState implements Disposable {
|
||||
if (result instanceof RecalculatableResult) {
|
||||
shortenReferences();
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(myDocument);
|
||||
((RecalculatableResult) result).handleRecalc(psiFile, myDocument,
|
||||
mySegments.getSegmentStart(segmentNumber), mySegments.getSegmentEnd(segmentNumber));
|
||||
((RecalculatableResult)result)
|
||||
.handleRecalc(psiFile, myDocument, mySegments.getSegmentStart(segmentNumber), mySegments.getSegmentEnd(segmentNumber));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,11 +639,9 @@ public class TemplateState implements Disposable {
|
||||
mySegments.setNeighboursGreedy(segmentNumber, true);
|
||||
|
||||
if (segmentNumberWithTheSameStart != -1) {
|
||||
mySegments.replaceSegmentAt(
|
||||
segmentNumberWithTheSameStart,
|
||||
newEnd,
|
||||
newEnd + mySegments.getSegmentEnd(segmentNumberWithTheSameStart) - mySegments.getSegmentStart(segmentNumberWithTheSameStart)
|
||||
);
|
||||
mySegments.replaceSegmentAt(segmentNumberWithTheSameStart, newEnd,
|
||||
newEnd + mySegments.getSegmentEnd(segmentNumberWithTheSameStart) -
|
||||
mySegments.getSegmentStart(segmentNumberWithTheSameStart));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -723,7 +728,7 @@ public class TemplateState implements Disposable {
|
||||
}
|
||||
|
||||
public <T> T getProperty(Key<T> key) {
|
||||
return (T) myProperties.get(key);
|
||||
return (T)myProperties.get(key);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -743,7 +748,8 @@ public class TemplateState implements Disposable {
|
||||
int offset = -1;
|
||||
if (endSegmentNumber >= 0) {
|
||||
offset = mySegments.getSegmentStart(endSegmentNumber);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!myTemplate.isSelectionTemplate() && !myTemplate.isInline()) { //do not move caret to the end of range for selection templates
|
||||
offset = myTemplateRange.getEndOffset();
|
||||
}
|
||||
@@ -758,10 +764,7 @@ public class TemplateState implements Disposable {
|
||||
int selStart = myTemplate.getSelectionStartSegmentNumber();
|
||||
int selEnd = myTemplate.getSelectionEndSegmentNumber();
|
||||
if (selStart >= 0 && selEnd >= 0) {
|
||||
myEditor.getSelectionModel().setSelection(
|
||||
mySegments.getSegmentStart(selStart),
|
||||
mySegments.getSegmentStart(selEnd)
|
||||
);
|
||||
myEditor.getSelectionModel().setSelection(mySegments.getSegmentStart(selStart), mySegments.getSegmentStart(selEnd));
|
||||
}
|
||||
fireBeforeTemplateFinished();
|
||||
final Editor editor = myEditor;
|
||||
@@ -797,10 +800,12 @@ public class TemplateState implements Disposable {
|
||||
if (expression == null) {
|
||||
return false;
|
||||
}
|
||||
if (myTemplate.isAlwaysStopAt(currentVariableNumber)) {
|
||||
return true;
|
||||
}
|
||||
String variableName = myTemplate.getVariableNameAt(currentVariableNumber);
|
||||
if (!(TemplateImpl.ARG.equals(variableName) && myArgument != null)) {
|
||||
if (myTemplate.isAlwaysStopAt(currentVariableNumber)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
int segmentNumber = myTemplate.getVariableSegmentNumber(variableName);
|
||||
if (segmentNumber < 0) return false;
|
||||
int start = mySegments.getSegmentStart(segmentNumber);
|
||||
@@ -867,9 +872,7 @@ public class TemplateState implements Disposable {
|
||||
}
|
||||
|
||||
private RangeHighlighter getSegmentHighlighter(int segmentNumber, boolean isSelected, boolean isEnd) {
|
||||
TextAttributes attributes = isSelected
|
||||
? new TextAttributes(null, null, Color.red, EffectType.BOXED, Font.PLAIN)
|
||||
: new TextAttributes();
|
||||
TextAttributes attributes = isSelected ? new TextAttributes(null, null, Color.red, EffectType.BOXED, Font.PLAIN) : new TextAttributes();
|
||||
TextAttributes endAttributes = new TextAttributes();
|
||||
|
||||
RangeHighlighter segmentHighlighter;
|
||||
@@ -880,8 +883,8 @@ public class TemplateState implements Disposable {
|
||||
.addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, endAttributes, HighlighterTargetArea.EXACT_RANGE);
|
||||
}
|
||||
else {
|
||||
segmentHighlighter = myEditor.getMarkupModel()
|
||||
.addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, attributes, HighlighterTargetArea.EXACT_RANGE);
|
||||
segmentHighlighter =
|
||||
myEditor.getMarkupModel().addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, attributes, HighlighterTargetArea.EXACT_RANGE);
|
||||
}
|
||||
segmentHighlighter.setGreedyToLeft(true);
|
||||
segmentHighlighter.setGreedyToRight(true);
|
||||
@@ -910,7 +913,7 @@ public class TemplateState implements Disposable {
|
||||
final PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
|
||||
if (file != null) {
|
||||
CodeStyleManager style = CodeStyleManager.getInstance(myProject);
|
||||
for(TemplateOptionalProcessor optionalProcessor : Extensions.getExtensions(TemplateOptionalProcessor.EP_NAME)) {
|
||||
for (TemplateOptionalProcessor optionalProcessor : Extensions.getExtensions(TemplateOptionalProcessor.EP_NAME)) {
|
||||
optionalProcessor.processText(myProject, myTemplate, myDocument, myTemplateRange, myEditor);
|
||||
}
|
||||
if (myTemplate.isToReformat()) {
|
||||
@@ -921,7 +924,7 @@ public class TemplateState implements Disposable {
|
||||
if (endSegmentNumber >= 0) {
|
||||
int endVarOffset = mySegments.getSegmentStart(endSegmentNumber);
|
||||
PsiElement marker = style.insertNewLineIndentMarker(file, endVarOffset);
|
||||
if(marker != null) rangeMarker = myDocument.createRangeMarker(marker.getTextRange());
|
||||
if (marker != null) rangeMarker = myDocument.createRangeMarker(marker.getTextRange());
|
||||
}
|
||||
style.reformatText(file, myTemplateRange.getStartOffset(), myTemplateRange.getEndOffset());
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(myDocument);
|
||||
|
||||
@@ -254,6 +254,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
boolean completed = JobUtil.invokeConcurrentlyUnderMyProgress(new ArrayList<PsiFile>(fileSet), new Processor<PsiFile>() {
|
||||
public boolean process(final PsiFile file) {
|
||||
if (file instanceof PsiBinaryFile) return true;
|
||||
file.getViewProvider().getContents(); // load contents outside readaction
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
@@ -73,7 +73,7 @@ public abstract class Task implements TaskInfo {
|
||||
return myTitle;
|
||||
}
|
||||
|
||||
public final Task setTitle(final String title) {
|
||||
public final Task setTitle(@NotNull String title) {
|
||||
myTitle = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -347,6 +347,9 @@ public class VfsUtil {
|
||||
|
||||
if (file == null && uri.contains(JarFileSystem.JAR_SEPARATOR)) {
|
||||
file = JarFileSystem.getInstance().findFileByPath(uri);
|
||||
if (file == null && base == null) {
|
||||
file = VirtualFileManager.getInstance().findFileByUrl(uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (file == null) {
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.ex.WindowManagerEx;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public abstract class WindowAction extends AnAction {
|
||||
|
||||
public static final String NO_WINDOW_ACTIONS = "no.window.actions";
|
||||
|
||||
protected Window myWindow;
|
||||
private static JLabel mySizeHelper = new JLabel("W");
|
||||
|
||||
{
|
||||
setEnabledInModalContext(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void update(AnActionEvent e) {
|
||||
Window wnd = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();
|
||||
e.getPresentation().setEnabled(wnd != null && !(wnd instanceof IdeFrame));
|
||||
|
||||
Object noActions = null;
|
||||
if (wnd instanceof JDialog) {
|
||||
noActions = ((JDialog)wnd).getRootPane().getClientProperty(NO_WINDOW_ACTIONS);
|
||||
} else if (wnd instanceof JFrame) {
|
||||
noActions = ((JFrame)wnd).getRootPane().getClientProperty(NO_WINDOW_ACTIONS);
|
||||
}
|
||||
|
||||
if (noActions != null && "true".equalsIgnoreCase(noActions.toString())) {
|
||||
e.getPresentation().setEnabled(false);
|
||||
}
|
||||
|
||||
if (e.getPresentation().isEnabled()) {
|
||||
myWindow = wnd;
|
||||
} else {
|
||||
myWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class BaseSizeAction extends WindowAction {
|
||||
|
||||
private boolean myHorizontal;
|
||||
private boolean myPositive;
|
||||
|
||||
protected BaseSizeAction(boolean horizontal, boolean positive) {
|
||||
myHorizontal = horizontal;
|
||||
myPositive = positive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
int baseValue = myHorizontal ? mySizeHelper.getPreferredSize().width : mySizeHelper.getPreferredSize().height;
|
||||
|
||||
int inc = baseValue * (myHorizontal ? Registry.intValue("ide.windowSystem.hScrollChars") : Registry.intValue("ide.windowSystem.vScrollChars"));
|
||||
if (!myPositive) {
|
||||
inc = -inc;
|
||||
}
|
||||
|
||||
Rectangle bounds = myWindow.getBounds();
|
||||
if (myHorizontal) {
|
||||
bounds.width += inc;
|
||||
} else {
|
||||
bounds.height += inc;
|
||||
}
|
||||
|
||||
myWindow.setBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IncrementWidth extends BaseSizeAction {
|
||||
|
||||
public IncrementWidth() {
|
||||
super(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DecrementWidth extends BaseSizeAction {
|
||||
|
||||
public DecrementWidth() {
|
||||
super(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IncrementHeight extends BaseSizeAction {
|
||||
public IncrementHeight() {
|
||||
super(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DecrementHeight extends BaseSizeAction {
|
||||
public DecrementHeight() {
|
||||
super(false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,6 +301,8 @@ public class KeymapImpl implements Keymap, ExternalizableScheme {
|
||||
}
|
||||
|
||||
private THashMap<KeyStroke,ArrayList<String>> getKeystroke2ListOfIds() {
|
||||
myKeystroke2ListOfIds = null;
|
||||
|
||||
if (myKeystroke2ListOfIds == null) {
|
||||
myKeystroke2ListOfIds = new THashMap<KeyStroke, ArrayList<String>>();
|
||||
fillKeystroke2ListOfIds(myKeystroke2ListOfIds, KeyboardShortcut.class);
|
||||
|
||||
@@ -708,6 +708,10 @@ action.ResizeToolWindowUp.text=Stretch to Top
|
||||
action.ResizeToolWindowUp.description=Resize active tool window to the top
|
||||
action.ResizeToolWindowDown.text=Stretch to Bottom
|
||||
action.ResizeToolWindowDown.description=Resize active tool window to the bottom
|
||||
action.IncrementWindowWidth.text=Increment Width
|
||||
action.DecrementWindowWidth.text=Decrement Width
|
||||
action.IncrementWindowHeight.text=Increment Height
|
||||
action.DecrementWindowHeight.text=Decrement Height
|
||||
action.NextTab.text=Select Ne_xt Tab
|
||||
action.NextTab.description=Activate next tab
|
||||
action.PreviousTab.text=Se_lect Previous Tab
|
||||
|
||||
@@ -402,5 +402,10 @@
|
||||
</group>
|
||||
|
||||
<action id="Rerun" class="com.intellij.execution.runners.FakeRerunAction" text="Rerun"/>
|
||||
|
||||
<action id="IncrementWindowWidth" class="com.intellij.ide.actions.WindowAction$IncrementWidth" use-shortcut-of="ResizeToolWindowRight"/>
|
||||
<action id="DecrementWindowWidth" class="com.intellij.ide.actions.WindowAction$DecrementWidth" use-shortcut-of="ResizeToolWindowLeft"/>
|
||||
<action id="IncrementWindowHeight" class="com.intellij.ide.actions.WindowAction$IncrementHeight" use-shortcut-of="ResizeToolWindowDown"/>
|
||||
<action id="DecrementWindowHeight" class="com.intellij.ide.actions.WindowAction$DecrementHeight" use-shortcut-of="ResizeToolWindowUp"/>
|
||||
</actions>
|
||||
</component>
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij;
|
||||
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
@@ -51,7 +52,7 @@ public class CommonBundle {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public static String messageOrDefault(@Nullable final ResourceBundle bundle, final String key, final @Nullable String defaultValue, final Object... params) {
|
||||
public static String messageOrDefault(@Nullable final ResourceBundle bundle, final String key, @Nullable final String defaultValue, final Object... params) {
|
||||
if (bundle == null) return defaultValue;
|
||||
|
||||
String value;
|
||||
@@ -64,7 +65,7 @@ public class CommonBundle {
|
||||
} else {
|
||||
value = "!" + key + "!";
|
||||
if (assertKeyIsFound) {
|
||||
assert false: key + " is not found";
|
||||
assert false: key + " is not found in "+BUNDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +83,7 @@ public class CommonBundle {
|
||||
return messageOrDefault(bundle, key, null, params);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getCancelButtonText() {
|
||||
return message("button.cancel");
|
||||
}
|
||||
|
||||
@@ -39,15 +39,10 @@ import org.jetbrains.plugins.groovy.codeInspection.GroovyImportsTracker;
|
||||
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
|
||||
import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter;
|
||||
import org.jetbrains.plugins.groovy.intentions.utils.DuplicatesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.*;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
@@ -86,9 +81,11 @@ import java.util.*;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class GroovyAnnotator implements Annotator {
|
||||
public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.annotator.GroovyAnnotator");
|
||||
|
||||
private AnnotationHolder myHolder;
|
||||
|
||||
private static boolean isDocCommentElement(PsiElement element) {
|
||||
if (element == null) return false;
|
||||
ASTNode node = element.getNode();
|
||||
@@ -96,87 +93,21 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if (element instanceof GrCodeReferenceElement) {
|
||||
checkReferenceElement(holder, (GrCodeReferenceElement)element);
|
||||
if (element instanceof GroovyPsiElement) {
|
||||
myHolder = holder;
|
||||
((GroovyPsiElement)element).accept(this);
|
||||
myHolder = null;
|
||||
}
|
||||
else if (element instanceof GrReferenceExpression) {
|
||||
checkReferenceExpression(holder, (GrReferenceExpression)element);
|
||||
}
|
||||
else if (element instanceof GrTypeDefinition) {
|
||||
final GrTypeDefinition typeDefinition = (GrTypeDefinition)element;
|
||||
checkTypeDefinition(holder, typeDefinition);
|
||||
checkTypeDefinitionModifiers(holder, typeDefinition);
|
||||
final GrTypeDefinitionBody body = typeDefinition.getBody();
|
||||
if (body != null) checkDuplicateMethod(body.getGroovyMethods(), holder);
|
||||
checkImplementedMethodsOfClass(holder, typeDefinition);
|
||||
}
|
||||
else if (element instanceof GrMethod) {
|
||||
final GrMethod method = (GrMethod)element;
|
||||
checkMethodDefinitionModifiers(holder, method);
|
||||
checkInnerMethod(holder, method);
|
||||
}
|
||||
else if (element instanceof GrVariableDeclaration) {
|
||||
checkVariableDeclaration(holder, (GrVariableDeclaration)element);
|
||||
}
|
||||
else if (element instanceof GrVariable) {
|
||||
if (element instanceof GrMember) {
|
||||
highlightMember(holder, ((GrMember)element));
|
||||
checkStaticDeclarationsInInnerClass((GrMember)element, holder);
|
||||
}
|
||||
checkVariable(holder, (GrVariable)element);
|
||||
}
|
||||
else if (element instanceof GrAssignmentExpression) {
|
||||
checkAssignmentExpression((GrAssignmentExpression)element, holder);
|
||||
}
|
||||
else if (element instanceof GrReturnStatement) {
|
||||
checkReturnStatement((GrReturnStatement)element, holder);
|
||||
}
|
||||
else if (element instanceof GrListOrMap) {
|
||||
checkMap(((GrListOrMap)element).getNamedArguments(), holder);
|
||||
}
|
||||
else if (element instanceof GrNewExpression) {
|
||||
checkNewExpression(holder, (GrNewExpression)element);
|
||||
}
|
||||
else if (element instanceof GrDocMemberReference) {
|
||||
checkGrDocMemberReference((GrDocMemberReference)element, holder);
|
||||
}
|
||||
else if (element instanceof GrConstructorInvocation) {
|
||||
checkConstructorInvocation(holder, (GrConstructorInvocation)element);
|
||||
}
|
||||
else if (element instanceof GrFlowInterruptingStatement) {
|
||||
checkFlowInterruptStatement(((GrFlowInterruptingStatement)element), holder);
|
||||
} else if (element instanceof GrLabeledStatement) {
|
||||
checkLabeledStatement(((GrLabeledStatement) element), holder);
|
||||
}
|
||||
else if (element.getParent() instanceof GrDocReferenceElement) {
|
||||
checkGrDocReferenceElement(holder, element);
|
||||
}
|
||||
else if (element instanceof GrPackageDefinition) {
|
||||
//todo: if reference isn't resolved it construct package definition
|
||||
checkPackageReference(holder, (GrPackageDefinition)element);
|
||||
}
|
||||
else if (element instanceof GrThisReferenceExpression || element instanceof GrSuperReferenceExpression) {
|
||||
checkThisOrSuperReferenceExpression(((GrExpression)element), holder);
|
||||
}
|
||||
else if (element instanceof GrLiteral) {
|
||||
checkLiteral(((GrLiteral)element), holder);
|
||||
}
|
||||
else if (element instanceof GrForInClause) {
|
||||
checkForInClause(((GrForInClause)element), holder);
|
||||
}
|
||||
else if (element instanceof GroovyFile) {
|
||||
final GroovyFile file = (GroovyFile)element;
|
||||
if (file.isScript()) {
|
||||
checkScriptDuplicateMethod(file.getTopLevelDefinitions(), holder);
|
||||
}
|
||||
}
|
||||
else if (element instanceof GrImportStatement) {
|
||||
checkAnnotationList(holder, ((GrImportStatement)element).getAnnotationList(), GroovyBundle.message("import.statement.cannot.have.modifiers"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitElement(GroovyPsiElement element) {
|
||||
if (element.getParent() instanceof GrDocReferenceElement) {
|
||||
checkGrDocReferenceElement(myHolder, element);
|
||||
}
|
||||
else {
|
||||
final ASTNode node = element.getNode();
|
||||
if (node != null &&
|
||||
!(element instanceof PsiWhiteSpace) &&
|
||||
if (!(element instanceof PsiWhiteSpace) &&
|
||||
!GroovyTokenTypes.COMMENT_SET.contains(node.getElementType()) &&
|
||||
element.getContainingFile() instanceof GroovyFile &&
|
||||
!isDocCommentElement(element)) {
|
||||
@@ -185,7 +116,377 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkForInClause(GrForInClause forInClause, AnnotationHolder holder) {
|
||||
@Override
|
||||
public void visitCodeReferenceElement(GrCodeReferenceElement refElement) {
|
||||
final PsiElement parent = refElement.getParent();
|
||||
GroovyResolveResult resolveResult = refElement.advancedResolve();
|
||||
highlightAnnotation(myHolder, refElement, resolveResult);
|
||||
registerUsedImport(refElement, resolveResult);
|
||||
highlightAnnotation(myHolder, refElement, resolveResult);
|
||||
if (refElement.getReferenceName() != null) {
|
||||
|
||||
if (parent instanceof GrImportStatement && ((GrImportStatement)parent).isStatic() && refElement.multiResolve(false).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkSingleResolvedElement(myHolder, refElement, resolveResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(GrReferenceExpression referenceExpression) {
|
||||
GroovyResolveResult resolveResult = referenceExpression.advancedResolve();
|
||||
GroovyResolveResult[] results = referenceExpression.multiResolve(false); //cached
|
||||
for (GroovyResolveResult result : results) {
|
||||
registerUsedImport(referenceExpression, result);
|
||||
}
|
||||
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
final PsiElement parent = referenceExpression.getParent();
|
||||
if (resolved != null) {
|
||||
if (resolved instanceof PsiMember) {
|
||||
highlightMemberResolved(myHolder, referenceExpression, ((PsiMember)resolved));
|
||||
}
|
||||
if (!resolveResult.isAccessible()) {
|
||||
String message = GroovyBundle.message("cannot.access", referenceExpression.getReferenceName());
|
||||
myHolder.createWarningAnnotation(referenceExpression.getReferenceNameElement(), message);
|
||||
}
|
||||
if (!resolveResult.isStaticsOK() && resolved instanceof PsiModifierListOwner) {
|
||||
if (!((PsiModifierListOwner)resolved).hasModifierProperty(PsiModifier.STATIC)) {
|
||||
myHolder.createWarningAnnotation(referenceExpression, GroovyBundle.message("cannot.reference.nonstatic", referenceExpression.getReferenceName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
GrExpression qualifier = referenceExpression.getQualifierExpression();
|
||||
if (qualifier == null && isDeclarationAssignment(referenceExpression)) return;
|
||||
|
||||
if (parent instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)parent).getReferenceName())) {
|
||||
checkSingleResolvedElement(myHolder, referenceExpression, resolveResult);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent instanceof GrCall) {
|
||||
if (resolved == null && results.length > 0) {
|
||||
resolved = results[0].getElement();
|
||||
resolveResult = results[0];
|
||||
}
|
||||
if (resolved instanceof PsiMethod && resolved.getUserData(GrMethod.BUILDER_METHOD) == null) {
|
||||
checkMethodApplicability(resolveResult, referenceExpression, myHolder);
|
||||
}
|
||||
else {
|
||||
checkClosureApplicability(resolveResult, referenceExpression.getType(), referenceExpression, myHolder);
|
||||
}
|
||||
}
|
||||
if (isDeclarationAssignment(referenceExpression) || resolved instanceof PsiPackage) return;
|
||||
|
||||
if (resolved == null) {
|
||||
PsiElement refNameElement = referenceExpression.getReferenceNameElement();
|
||||
PsiElement elt = refNameElement == null ? referenceExpression : refNameElement;
|
||||
Annotation annotation = myHolder.createInfoAnnotation(elt, null);
|
||||
final GrExpression qualifier = referenceExpression.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
if (!(parent instanceof GrCall)) {
|
||||
registerCreateClassByTypeFix(referenceExpression, annotation);
|
||||
registerAddImportFixes(referenceExpression, annotation);
|
||||
}
|
||||
} else {
|
||||
if (qualifier.getType() == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerReferenceFixes(referenceExpression, annotation);
|
||||
annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeDefinition(GrTypeDefinition typeDefinition) {
|
||||
checkTypeDefinition(myHolder, typeDefinition);
|
||||
checkTypeDefinitionModifiers(myHolder, typeDefinition);
|
||||
|
||||
final GrTypeDefinitionBody body = typeDefinition.getBody();
|
||||
if (body != null) checkDuplicateMethod(body.getGroovyMethods(), myHolder);
|
||||
checkImplementedMethodsOfClass(myHolder, typeDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(GrMethod method) {
|
||||
checkMethodDefinitionModifiers(myHolder, method);
|
||||
checkInnerMethod(myHolder, method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVariableDeclaration(GrVariableDeclaration variableDeclaration) {
|
||||
|
||||
PsiElement parent = variableDeclaration.getParent();
|
||||
assert parent != null;
|
||||
|
||||
PsiElement typeDef = parent.getParent();
|
||||
if (typeDef != null && typeDef instanceof GrTypeDefinition) {
|
||||
PsiModifierList modifiersList = variableDeclaration.getModifierList();
|
||||
checkAccessModifiers(myHolder, modifiersList);
|
||||
|
||||
if (modifiersList.hasExplicitModifier(PsiModifier.VOLATILE) && modifiersList.hasExplicitModifier(PsiModifier.FINAL)) {
|
||||
myHolder.createErrorAnnotation(modifiersList, GroovyBundle.message("illegal.combination.of.modifiers.volatile.and.final"));
|
||||
}
|
||||
|
||||
if (modifiersList.hasExplicitModifier(PsiModifier.NATIVE)) {
|
||||
myHolder.createErrorAnnotation(modifiersList, GroovyBundle.message("variable.cannot.be.native"));
|
||||
}
|
||||
|
||||
if (modifiersList.hasExplicitModifier(PsiModifier.ABSTRACT)) {
|
||||
myHolder.createErrorAnnotation(modifiersList, GroovyBundle.message("variable.cannot.be.abstract"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVariable(GrVariable variable) {
|
||||
if (variable instanceof GrMember) {
|
||||
highlightMember(myHolder, ((GrMember)variable));
|
||||
checkStaticDeclarationsInInnerClass((GrMember)variable, myHolder);
|
||||
}
|
||||
PropertyResolverProcessor processor = new DuplicateVariablesProcessor(variable);
|
||||
final GroovyPsiElement duplicate =
|
||||
ResolveUtil.resolveExistingElement(variable, processor, GrVariable.class, GrReferenceExpression.class);
|
||||
|
||||
if (duplicate instanceof GrVariable) {
|
||||
if (duplicate instanceof GrField && !(variable instanceof GrField)) {
|
||||
myHolder
|
||||
.createWarningAnnotation(variable.getNameIdentifierGroovy(), GroovyBundle.message("field.already.defined", variable.getName()));
|
||||
}
|
||||
else {
|
||||
final String key = duplicate instanceof GrField ? "field.already.defined" : "variable.already.defined";
|
||||
myHolder.createErrorAnnotation(variable.getNameIdentifierGroovy(), GroovyBundle.message(key, variable.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAssignmentExpression(GrAssignmentExpression expression) {
|
||||
GrExpression lValue = expression.getLValue();
|
||||
if (!PsiUtil.mightBeLVlaue(lValue)) {
|
||||
myHolder.createErrorAnnotation(lValue, GroovyBundle.message("invalid.lvalue"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturnStatement(GrReturnStatement returnStatement) {
|
||||
final GrExpression value = returnStatement.getReturnValue();
|
||||
if (value != null) {
|
||||
final PsiType type = value.getType();
|
||||
if (type != null) {
|
||||
final GrParametersOwner owner = PsiTreeUtil.getParentOfType(returnStatement, GrMethod.class, GrClosableBlock.class);
|
||||
if (owner instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)owner;
|
||||
if (method.isConstructor()) {
|
||||
myHolder.createErrorAnnotation(value, GroovyBundle.message("cannot.return.from.constructor"));
|
||||
}
|
||||
else {
|
||||
final PsiType methodType = method.getReturnType();
|
||||
if (methodType != null) {
|
||||
if (PsiType.VOID.equals(methodType)) {
|
||||
myHolder.createErrorAnnotation(value, GroovyBundle.message("cannot.return.from.void.method"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitListOrMap(GrListOrMap listOrMap) {
|
||||
final Map<GrNamedArgument, List<GrNamedArgument>> map = DuplicatesUtil.factorDuplicates(listOrMap.getNamedArguments(), new TObjectHashingStrategy<GrNamedArgument>() {
|
||||
public int computeHashCode(GrNamedArgument arg) {
|
||||
final GrArgumentLabel label = arg.getLabel();
|
||||
if (label == null) return 0;
|
||||
final String name = label.getName();
|
||||
if (name == null) return 0;
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(GrNamedArgument arg1, GrNamedArgument arg2) {
|
||||
final GrArgumentLabel label1 = arg1.getLabel();
|
||||
final GrArgumentLabel label2 = arg2.getLabel();
|
||||
if (label1 == null || label2 == null) {
|
||||
return label1 == null && label2 == null;
|
||||
}
|
||||
final String name1 = label1.getName();
|
||||
final String name2 = label2.getName();
|
||||
if (name1 == null || name2 == null) {
|
||||
return name1 == null && name2 == null;
|
||||
}
|
||||
return name1.equals(name2);
|
||||
}
|
||||
});
|
||||
|
||||
processDuplicates(map, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewExpression(GrNewExpression newExpression) {
|
||||
if (newExpression.getArrayCount() > 0) return;
|
||||
GrCodeReferenceElement refElement = newExpression.getReferenceElement();
|
||||
if (refElement == null) return;
|
||||
final PsiElement element = refElement.resolve();
|
||||
if (element instanceof PsiClass) {
|
||||
PsiClass clazz = (PsiClass)element;
|
||||
if (clazz.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
if (newExpression.getAnonymousClassDefinition() == null) {
|
||||
String message = clazz.isInterface()
|
||||
? GroovyBundle.message("cannot.instantiate.interface", clazz.getName())
|
||||
: GroovyBundle.message("cannot.instantiate.abstract.class", clazz.getName());
|
||||
myHolder.createErrorAnnotation(refElement, message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (newExpression.getQualifier() != null) {
|
||||
if (clazz.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
myHolder.createErrorAnnotation(newExpression, GroovyBundle.message("qualified.new.of.static.class"));
|
||||
}
|
||||
} else {
|
||||
final PsiClass outerClass = clazz.getContainingClass();
|
||||
if (com.intellij.psi.util.PsiUtil.isInnerClass(clazz) && !PsiUtil.hasEnclosingInstanceInScope(outerClass, newExpression, true)) {
|
||||
myHolder.createErrorAnnotation(newExpression, GroovyBundle.message("cannot.reference.nonstatic", clazz.getQualifiedName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final GroovyResolveResult constructorResolveResult = newExpression.resolveConstructorGenerics();
|
||||
if (constructorResolveResult.getElement() != null) {
|
||||
checkMethodApplicability(constructorResolveResult, refElement, myHolder);
|
||||
final GrArgumentList argList = newExpression.getArgumentList();
|
||||
if (argList != null && argList.getExpressionArguments().length == 0) checkDefaultMapConstructor(myHolder, argList);
|
||||
}
|
||||
else {
|
||||
final GroovyResolveResult[] results = newExpression.multiResolveConstructor();
|
||||
final GrArgumentList argList = newExpression.getArgumentList();
|
||||
PsiElement toHighlight = argList != null ? argList : refElement.getReferenceNameElement();
|
||||
|
||||
if (results.length > 0) {
|
||||
String message = GroovyBundle.message("ambiguous.constructor.call");
|
||||
myHolder.createWarningAnnotation(toHighlight, message);
|
||||
}
|
||||
else {
|
||||
if (element instanceof PsiClass) {
|
||||
//default constructor invocation
|
||||
PsiType[] argumentTypes = PsiUtil.getArgumentTypes(refElement, true, true);
|
||||
if (argumentTypes != null && argumentTypes.length > 0) {
|
||||
String message = GroovyBundle.message("cannot.find.default.constructor", ((PsiClass)element).getName());
|
||||
myHolder.createWarningAnnotation(toHighlight, message);
|
||||
}
|
||||
else checkDefaultMapConstructor(myHolder, argList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDocMethodReference(GrDocMethodReference reference) {
|
||||
checkGrDocMemberReference(reference, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDocFieldReference(GrDocFieldReference reference) {
|
||||
checkGrDocMemberReference(reference, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstructorInvocation(GrConstructorInvocation invocation) {
|
||||
final GroovyResolveResult resolveResult = invocation.resolveConstructorGenerics();
|
||||
if (resolveResult != null) {
|
||||
checkMethodApplicability(resolveResult, invocation.getThisOrSuperKeyword(), myHolder);
|
||||
}
|
||||
else {
|
||||
final GroovyResolveResult[] results = invocation.multiResolveConstructor();
|
||||
final GrArgumentList argList = invocation.getArgumentList();
|
||||
if (results.length > 0) {
|
||||
String message = GroovyBundle.message("ambiguous.constructor.call");
|
||||
myHolder.createWarningAnnotation(argList, message);
|
||||
}
|
||||
else {
|
||||
final PsiClass clazz = invocation.getDelegatedClass();
|
||||
if (clazz != null) {
|
||||
//default constructor invocation
|
||||
PsiType[] argumentTypes = PsiUtil.getArgumentTypes(invocation.getThisOrSuperKeyword(), true, true);
|
||||
if (argumentTypes != null && argumentTypes.length > 0) {
|
||||
String message = GroovyBundle.message("cannot.find.default.constructor", clazz.getName());
|
||||
myHolder.createWarningAnnotation(argList, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBreakStatement(GrBreakStatement breakStatement) {
|
||||
checkFlowInterruptStatement(breakStatement, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitContinueStatement(GrContinueStatement continueStatement) {
|
||||
checkFlowInterruptStatement(continueStatement, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLabeledStatement(GrLabeledStatement labeledStatement) {
|
||||
final String name = labeledStatement.getLabelName();
|
||||
if (ResolveUtil.resolveLabeledStatement(name, labeledStatement, true) != null) {
|
||||
myHolder.createWarningAnnotation(labeledStatement.getLabel(), GroovyBundle.message("label.already.used", name));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPackageDefinition(GrPackageDefinition packageDefinition) {
|
||||
//todo: if reference isn't resolved it construct package definition
|
||||
final PsiFile file = packageDefinition.getContainingFile();
|
||||
assert file != null;
|
||||
|
||||
PsiDirectory psiDirectory = file.getContainingDirectory();
|
||||
if (psiDirectory != null) {
|
||||
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(psiDirectory);
|
||||
if (aPackage != null) {
|
||||
String packageName = aPackage.getQualifiedName();
|
||||
if (!packageDefinition.getPackageName().equals(packageName)) {
|
||||
final Annotation annotation = myHolder.createWarningAnnotation(packageDefinition, "wrong package name");
|
||||
annotation.registerFix(new ChangePackageQuickFix((GroovyFile)packageDefinition.getContainingFile(), packageName));
|
||||
}
|
||||
}
|
||||
}
|
||||
final GrModifierList modifierList = packageDefinition.getAnnotationList();
|
||||
checkAnnotationList(myHolder, modifierList, GroovyBundle.message("package.definition.cannot.have.modifiers"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSuperExpression(GrSuperReferenceExpression superExpression) {
|
||||
checkThisOrSuperReferenceExpression(superExpression, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThisExpression(GrThisReferenceExpression thisExpression) {
|
||||
checkThisOrSuperReferenceExpression(thisExpression, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLiteralExpression(GrLiteral literal) {
|
||||
String text = literal.getText();
|
||||
if (text.startsWith("'''")) {
|
||||
if (text.length() < 6 || !text.endsWith("'''")) {
|
||||
myHolder.createErrorAnnotation(literal, GroovyBundle.message("string.end.expected"));
|
||||
}
|
||||
}
|
||||
else if (text.startsWith("'")) {
|
||||
if (text.length() < 2 || !text.endsWith("'")) {
|
||||
myHolder.createErrorAnnotation(literal, GroovyBundle.message("string.end.expected"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitForInClause(GrForInClause forInClause) {
|
||||
final GrVariable[] declaredVariables = forInClause.getDeclaredVariables();
|
||||
if (declaredVariables.length < 1) return;
|
||||
final GrVariable variable = declaredVariables[0];
|
||||
@@ -197,29 +498,28 @@ public class GroovyAnnotator implements Annotator {
|
||||
final String modifierText = modifier.getText();
|
||||
if (PsiModifier.FINAL.equals(modifierText)) continue;
|
||||
if ("def".equals(modifierText)) continue;
|
||||
holder.createErrorAnnotation(modifier, GroovyBundle.message("not.allowed.modifier.in.forin", modifierText));
|
||||
myHolder.createErrorAnnotation(modifier, GroovyBundle.message("not.allowed.modifier.in.forin", modifierText));
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkLiteral(GrLiteral literal, AnnotationHolder holder) {
|
||||
String text = literal.getText();
|
||||
if (text.startsWith("'''")) {
|
||||
if (text.length() < 6 || !text.endsWith("'''")) {
|
||||
holder.createErrorAnnotation(literal, GroovyBundle.message("string.end.expected"));
|
||||
}
|
||||
}
|
||||
else if (text.startsWith("'")) {
|
||||
if (text.length() < 2 || !text.endsWith("'")) {
|
||||
holder.createErrorAnnotation(literal, GroovyBundle.message("string.end.expected"));
|
||||
@Override
|
||||
public void visitFile(GroovyFileBase file) {
|
||||
if (!file.isScript()) return;
|
||||
|
||||
List<GrMethod> methods = new ArrayList<GrMethod>();
|
||||
|
||||
for (GrTopLevelDefintion topLevelDefinition : file.getTopLevelDefinitions()) {
|
||||
if (topLevelDefinition instanceof GrMethod) {
|
||||
methods.add(((GrMethod)topLevelDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
checkDuplicateMethod(methods.toArray(new GrMethod[methods.size()]), myHolder);
|
||||
}
|
||||
|
||||
private static void checkLabeledStatement(GrLabeledStatement statement, AnnotationHolder holder) {
|
||||
final String name = statement.getLabelName();
|
||||
if (ResolveUtil.resolveLabeledStatement(name, statement, true) != null) {
|
||||
holder.createWarningAnnotation(statement.getLabel(), GroovyBundle.message("label.already.used", name));
|
||||
}
|
||||
@Override
|
||||
public void visitImportStatement(GrImportStatement importStatement) {
|
||||
checkAnnotationList(myHolder, importStatement.getAnnotationList(), GroovyBundle.message("import.statement.cannot.have.modifiers"));
|
||||
}
|
||||
|
||||
private static void checkFlowInterruptStatement(GrFlowInterruptingStatement statement, AnnotationHolder holder) {
|
||||
@@ -314,25 +614,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkPackageReference(AnnotationHolder holder, GrPackageDefinition packageDefinition) {
|
||||
final PsiFile file = packageDefinition.getContainingFile();
|
||||
assert file != null;
|
||||
|
||||
PsiDirectory psiDirectory = file.getContainingDirectory();
|
||||
if (psiDirectory != null) {
|
||||
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(psiDirectory);
|
||||
if (aPackage != null) {
|
||||
String packageName = aPackage.getQualifiedName();
|
||||
if (!packageDefinition.getPackageName().equals(packageName)) {
|
||||
final Annotation annotation = holder.createWarningAnnotation(packageDefinition, "wrong package name");
|
||||
annotation.registerFix(new ChangePackageQuickFix((GroovyFile)packageDefinition.getContainingFile(), packageName));
|
||||
}
|
||||
}
|
||||
}
|
||||
final GrModifierList modifierList = packageDefinition.getAnnotationList();
|
||||
checkAnnotationList(holder, modifierList, GroovyBundle.message("package.definition.cannot.have.modifiers"));
|
||||
}
|
||||
|
||||
private static void checkAnnotationList(AnnotationHolder holder, @Nullable GrModifierList modifierList, String message) {
|
||||
if (modifierList == null) return;
|
||||
final PsiElement[] modifiers = modifierList.getModifiers();
|
||||
@@ -366,32 +647,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
annotation.registerFix(new ImplementMethodsQuickFix(typeDefinition));
|
||||
}
|
||||
|
||||
private static void checkConstructorInvocation(AnnotationHolder holder, GrConstructorInvocation invocation) {
|
||||
final GroovyResolveResult resolveResult = invocation.resolveConstructorGenerics();
|
||||
if (resolveResult != null) {
|
||||
checkMethodApplicability(resolveResult, invocation.getThisOrSuperKeyword(), holder);
|
||||
}
|
||||
else {
|
||||
final GroovyResolveResult[] results = invocation.multiResolveConstructor();
|
||||
final GrArgumentList argList = invocation.getArgumentList();
|
||||
if (results.length > 0) {
|
||||
String message = GroovyBundle.message("ambiguous.constructor.call");
|
||||
holder.createWarningAnnotation(argList, message);
|
||||
}
|
||||
else {
|
||||
final PsiClass clazz = invocation.getDelegatedClass();
|
||||
if (clazz != null) {
|
||||
//default constructor invocation
|
||||
PsiType[] argumentTypes = PsiUtil.getArgumentTypes(invocation.getThisOrSuperKeyword(), true, true);
|
||||
if (argumentTypes != null && argumentTypes.length > 0) {
|
||||
String message = GroovyBundle.message("cannot.find.default.constructor", clazz.getName());
|
||||
holder.createWarningAnnotation(argList, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkInnerMethod(AnnotationHolder holder, GrMethod grMethod) {
|
||||
final PsiElement parent = grMethod.getParent();
|
||||
if (parent instanceof GrOpenBlock || parent instanceof GrClosableBlock) {
|
||||
@@ -399,34 +654,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkMap(GrNamedArgument[] namedArguments, AnnotationHolder holder) {
|
||||
final Map<GrNamedArgument, List<GrNamedArgument>> map = DuplicatesUtil.factorDuplicates(namedArguments, new TObjectHashingStrategy<GrNamedArgument>() {
|
||||
public int computeHashCode(GrNamedArgument arg) {
|
||||
final GrArgumentLabel label = arg.getLabel();
|
||||
if (label == null) return 0;
|
||||
final String name = label.getName();
|
||||
if (name == null) return 0;
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(GrNamedArgument arg1, GrNamedArgument arg2) {
|
||||
final GrArgumentLabel label1 = arg1.getLabel();
|
||||
final GrArgumentLabel label2 = arg2.getLabel();
|
||||
if (label1 == null || label2 == null) {
|
||||
return label1 == null && label2 == null;
|
||||
}
|
||||
final String name1 = label1.getName();
|
||||
final String name2 = label2.getName();
|
||||
if (name1 == null || name2 == null) {
|
||||
return name1 == null && name2 == null;
|
||||
}
|
||||
return name1.equals(name2);
|
||||
}
|
||||
});
|
||||
|
||||
processDuplicates(map, holder);
|
||||
}
|
||||
|
||||
protected static void processDuplicates(Map<GrNamedArgument, List<GrNamedArgument>> map, AnnotationHolder holder) {
|
||||
for (List<GrNamedArgument> args : map.values()) {
|
||||
for (int i = 1; i < args.size(); i++) {
|
||||
@@ -436,30 +663,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkVariableDeclaration(AnnotationHolder holder, GrVariableDeclaration variableDeclaration) {
|
||||
|
||||
PsiElement parent = variableDeclaration.getParent();
|
||||
assert parent != null;
|
||||
|
||||
PsiElement typeDef = parent.getParent();
|
||||
if (typeDef != null && typeDef instanceof GrTypeDefinition) {
|
||||
PsiModifierList modifiersList = variableDeclaration.getModifierList();
|
||||
checkAccessModifiers(holder, modifiersList);
|
||||
|
||||
if (modifiersList.hasExplicitModifier(PsiModifier.VOLATILE) && modifiersList.hasExplicitModifier(PsiModifier.FINAL)) {
|
||||
holder.createErrorAnnotation(modifiersList, GroovyBundle.message("illegal.combination.of.modifiers.volatile.and.final"));
|
||||
}
|
||||
|
||||
if (modifiersList.hasExplicitModifier(PsiModifier.NATIVE)) {
|
||||
holder.createErrorAnnotation(modifiersList, GroovyBundle.message("variable.cannot.be.native"));
|
||||
}
|
||||
|
||||
if (modifiersList.hasExplicitModifier(PsiModifier.ABSTRACT)) {
|
||||
holder.createErrorAnnotation(modifiersList, GroovyBundle.message("variable.cannot.be.abstract"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkMethodDefinitionModifiers(AnnotationHolder holder, GrMethod method) {
|
||||
final PsiModifierList modifiersList = method.getModifierList();
|
||||
checkAccessModifiers(holder, modifiersList);
|
||||
@@ -597,18 +800,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkScriptDuplicateMethod(GrTopLevelDefintion[] topLevelDefinitions, AnnotationHolder holder) {
|
||||
List<GrMethod> methods = new ArrayList<GrMethod>();
|
||||
|
||||
for (GrTopLevelDefintion topLevelDefinition : topLevelDefinitions) {
|
||||
if (topLevelDefinition instanceof GrMethod) {
|
||||
methods.add(((GrMethod)topLevelDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
checkDuplicateMethod(methods.toArray(new GrMethod[methods.size()]), holder);
|
||||
}
|
||||
|
||||
private static void checkDuplicateMethod(GrMethod[] methods, AnnotationHolder holder) {
|
||||
final Map<GrMethod, List<GrMethod>> map = DuplicatesUtil.factorDuplicates(methods, new TObjectHashingStrategy<GrMethod>() {
|
||||
public int computeHashCode(GrMethod method) {
|
||||
@@ -639,51 +830,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
|
||||
|
||||
private static void checkReturnStatement(GrReturnStatement returnStatement, AnnotationHolder holder) {
|
||||
final GrExpression value = returnStatement.getReturnValue();
|
||||
if (value != null) {
|
||||
final PsiType type = value.getType();
|
||||
if (type != null) {
|
||||
final GrParametersOwner owner = PsiTreeUtil.getParentOfType(returnStatement, GrMethod.class, GrClosableBlock.class);
|
||||
if (owner instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)owner;
|
||||
if (method.isConstructor()) {
|
||||
holder.createErrorAnnotation(value, GroovyBundle.message("cannot.return.from.constructor"));
|
||||
}
|
||||
else {
|
||||
final PsiType methodType = method.getReturnType();
|
||||
if (methodType != null) {
|
||||
if (PsiType.VOID.equals(methodType)) {
|
||||
holder.createErrorAnnotation(value, GroovyBundle.message("cannot.return.from.void.method"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkAssignmentExpression(GrAssignmentExpression assignment, AnnotationHolder holder) {
|
||||
GrExpression lValue = assignment.getLValue();
|
||||
if (!PsiUtil.mightBeLVlaue(lValue)) {
|
||||
holder.createErrorAnnotation(lValue, GroovyBundle.message("invalid.lvalue"));
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkVariable(AnnotationHolder holder, GrVariable variable) {
|
||||
PropertyResolverProcessor processor = new DuplicateVariablesProcessor(variable);
|
||||
final GroovyPsiElement duplicate = ResolveUtil.resolveExistingElement(variable, processor, GrVariable.class, GrReferenceExpression.class);
|
||||
|
||||
if (duplicate instanceof GrVariable) {
|
||||
if (duplicate instanceof GrField && !(variable instanceof GrField)) {
|
||||
holder.createWarningAnnotation(variable.getNameIdentifierGroovy(), GroovyBundle.message("field.already.defined", variable.getName()));
|
||||
} else {
|
||||
final String key = duplicate instanceof GrField ? "field.already.defined" : "variable.already.defined";
|
||||
holder.createErrorAnnotation(variable.getNameIdentifierGroovy(), GroovyBundle.message(key, variable.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkTypeDefinition(AnnotationHolder holder, GrTypeDefinition typeDefinition) {
|
||||
final GroovyConfigUtils configUtils = GroovyConfigUtils.getInstance();
|
||||
if (typeDefinition.isAnnotationType()) {
|
||||
@@ -804,72 +950,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkReferenceExpression(AnnotationHolder holder, final GrReferenceExpression refExpr) {
|
||||
GroovyResolveResult resolveResult = refExpr.advancedResolve();
|
||||
GroovyResolveResult[] results = refExpr.multiResolve(false); //cached
|
||||
for (GroovyResolveResult result : results) {
|
||||
registerUsedImport(refExpr, result);
|
||||
}
|
||||
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
final PsiElement parent = refExpr.getParent();
|
||||
if (resolved != null) {
|
||||
if (resolved instanceof PsiMember) {
|
||||
highlightMemberResolved(holder, refExpr, ((PsiMember)resolved));
|
||||
}
|
||||
if (!resolveResult.isAccessible()) {
|
||||
String message = GroovyBundle.message("cannot.access", refExpr.getReferenceName());
|
||||
holder.createWarningAnnotation(refExpr.getReferenceNameElement(), message);
|
||||
}
|
||||
if (!resolveResult.isStaticsOK() && resolved instanceof PsiModifierListOwner) {
|
||||
if (!((PsiModifierListOwner)resolved).hasModifierProperty(PsiModifier.STATIC)) {
|
||||
holder.createWarningAnnotation(refExpr, GroovyBundle.message("cannot.reference.nonstatic", refExpr.getReferenceName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
if (qualifier == null && isDeclarationAssignment(refExpr)) return;
|
||||
|
||||
if (parent instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)parent).getReferenceName())) {
|
||||
checkSingleResolvedElement(holder, refExpr, resolveResult);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent instanceof GrCall) {
|
||||
if (resolved == null && results.length > 0) {
|
||||
resolved = results[0].getElement();
|
||||
resolveResult = results[0];
|
||||
}
|
||||
if (resolved instanceof PsiMethod && resolved.getUserData(GrMethod.BUILDER_METHOD) == null) {
|
||||
checkMethodApplicability(resolveResult, refExpr, holder);
|
||||
}
|
||||
else {
|
||||
checkClosureApplicability(resolveResult, refExpr.getType(), refExpr, holder);
|
||||
}
|
||||
}
|
||||
if (isDeclarationAssignment(refExpr) || resolved instanceof PsiPackage) return;
|
||||
|
||||
if (resolved == null) {
|
||||
PsiElement refNameElement = refExpr.getReferenceNameElement();
|
||||
PsiElement elt = refNameElement == null ? refExpr : refNameElement;
|
||||
Annotation annotation = holder.createInfoAnnotation(elt, null);
|
||||
final GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
if (!(parent instanceof GrCall)) {
|
||||
registerCreateClassByTypeFix(refExpr, annotation);
|
||||
registerAddImportFixes(refExpr, annotation);
|
||||
}
|
||||
} else {
|
||||
if (qualifier.getType() == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerReferenceFixes(refExpr, annotation);
|
||||
annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS);
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerReferenceFixes(GrReferenceExpression refExpr, Annotation annotation) {
|
||||
PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr);
|
||||
if (targetClass == null) return;
|
||||
@@ -994,23 +1074,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void checkReferenceElement(AnnotationHolder holder, final GrCodeReferenceElement refElement) {
|
||||
final PsiElement parent = refElement.getParent();
|
||||
GroovyResolveResult resolveResult = refElement.advancedResolve();
|
||||
highlightAnnotation(holder, refElement, resolveResult);
|
||||
registerUsedImport(refElement, resolveResult);
|
||||
highlightAnnotation(holder, refElement, resolveResult);
|
||||
if (refElement.getReferenceName() != null) {
|
||||
|
||||
if (parent instanceof GrImportStatement && ((GrImportStatement)parent).isStatic() && refElement.multiResolve(false).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkSingleResolvedElement(holder, refElement, resolveResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void checkSingleResolvedElement(AnnotationHolder holder, GrReferenceElement refElement, GroovyResolveResult resolveResult) {
|
||||
final PsiElement resolved = resolveResult.getElement();
|
||||
if (resolved == null) {
|
||||
@@ -1033,63 +1096,6 @@ public class GroovyAnnotator implements Annotator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkNewExpression(AnnotationHolder holder, GrNewExpression newExpression) {
|
||||
if (newExpression.getArrayCount() > 0) return;
|
||||
GrCodeReferenceElement refElement = newExpression.getReferenceElement();
|
||||
if (refElement == null) return;
|
||||
final PsiElement element = refElement.resolve();
|
||||
if (element instanceof PsiClass) {
|
||||
PsiClass clazz = (PsiClass)element;
|
||||
if (clazz.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
if (newExpression.getAnonymousClassDefinition() == null) {
|
||||
String message = clazz.isInterface()
|
||||
? GroovyBundle.message("cannot.instantiate.interface", clazz.getName())
|
||||
: GroovyBundle.message("cannot.instantiate.abstract.class", clazz.getName());
|
||||
holder.createErrorAnnotation(refElement, message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (newExpression.getQualifier() != null) {
|
||||
if (clazz.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
holder.createErrorAnnotation(newExpression, GroovyBundle.message("qualified.new.of.static.class"));
|
||||
}
|
||||
} else {
|
||||
final PsiClass outerClass = clazz.getContainingClass();
|
||||
if (com.intellij.psi.util.PsiUtil.isInnerClass(clazz) && !PsiUtil.hasEnclosingInstanceInScope(outerClass, newExpression, true)) {
|
||||
holder.createErrorAnnotation(newExpression, GroovyBundle.message("cannot.reference.nonstatic", clazz.getQualifiedName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final GroovyResolveResult constructorResolveResult = newExpression.resolveConstructorGenerics();
|
||||
if (constructorResolveResult.getElement() != null) {
|
||||
checkMethodApplicability(constructorResolveResult, refElement, holder);
|
||||
final GrArgumentList argList = newExpression.getArgumentList();
|
||||
if (argList != null && argList.getExpressionArguments().length == 0) checkDefaultMapConstructor(holder, argList);
|
||||
}
|
||||
else {
|
||||
final GroovyResolveResult[] results = newExpression.multiResolveConstructor();
|
||||
final GrArgumentList argList = newExpression.getArgumentList();
|
||||
PsiElement toHighlight = argList != null ? argList : refElement.getReferenceNameElement();
|
||||
|
||||
if (results.length > 0) {
|
||||
String message = GroovyBundle.message("ambiguous.constructor.call");
|
||||
holder.createWarningAnnotation(toHighlight, message);
|
||||
}
|
||||
else {
|
||||
if (element instanceof PsiClass) {
|
||||
//default constructor invocation
|
||||
PsiType[] argumentTypes = PsiUtil.getArgumentTypes(refElement, true, true);
|
||||
if (argumentTypes != null && argumentTypes.length > 0) {
|
||||
String message = GroovyBundle.message("cannot.find.default.constructor", ((PsiClass)element).getName());
|
||||
holder.createWarningAnnotation(toHighlight, message);
|
||||
}
|
||||
else checkDefaultMapConstructor(holder, argList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkDefaultMapConstructor(AnnotationHolder holder, GrArgumentList argList) {
|
||||
if (argList != null) {
|
||||
final GrNamedArgument[] args = argList.getNamedArguments();
|
||||
|
||||
+84
-137
@@ -17,7 +17,10 @@ package org.jetbrains.plugins.groovy.compiler.generator;
|
||||
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.*;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.compiler.TimestampValidityState;
|
||||
import com.intellij.openapi.compiler.ValidityState;
|
||||
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.JavaModuleType;
|
||||
@@ -36,6 +39,7 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
@@ -68,8 +72,7 @@ import java.util.*;
|
||||
* @author: Dmitry.Krasilschikov
|
||||
* @date: 03.05.2007
|
||||
*/
|
||||
//todo it's not actually a compiler anymore, remove all the implements'
|
||||
public class GroovyToJavaGenerator implements SourceGeneratingCompiler, CompilationStatusListener {
|
||||
public class GroovyToJavaGenerator {
|
||||
private static final Map<String, String> typesToInitialValues = new HashMap<String, String>();
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.compiler.generator.GroovyToJavaGenerator");
|
||||
|
||||
@@ -100,12 +103,6 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
PsiModifier.VOLATILE
|
||||
};
|
||||
|
||||
private static final String[] JAVA_TYPE_DEFINITION_MODIFIERS = new String[]{
|
||||
PsiModifier.PUBLIC,
|
||||
PsiModifier.ABSTRACT,
|
||||
PsiModifier.FINAL
|
||||
};
|
||||
|
||||
private static final CharSequence PREFIX_SEPARATOR = "/";
|
||||
private final CompileContext myContext;
|
||||
private final Project myProject;
|
||||
@@ -149,7 +146,7 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
|
||||
//top level class
|
||||
if (needCreateTopLevelClass) {
|
||||
generationItems.add(new GenerationItemImpl(prefix + file.getNameWithoutExtension() + "." + "java", module, new TimestampValidityState(file.getTimeStamp()), isInTestSources, file));
|
||||
generationItems.add(new GenerationItem(prefix + file.getNameWithoutExtension() + "." + "java", module, new TimestampValidityState(file.getTimeStamp()), isInTestSources, file));
|
||||
}
|
||||
|
||||
GrTypeDefinition[] typeDefinitions = ApplicationManager.getApplication().runReadAction(new Computable<GrTypeDefinition[]>() {
|
||||
@@ -159,7 +156,7 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
});
|
||||
|
||||
for (GrTypeDefinition typeDefinition : typeDefinitions) {
|
||||
item = new GenerationItemImpl(prefix + typeDefinition.getName() + "." + "java", module, new TimestampValidityState(file.getTimeStamp()), isInTestSources, file);
|
||||
item = new GenerationItem(prefix + typeDefinition.getName() + "." + "java", module, new TimestampValidityState(file.getTimeStamp()), isInTestSources, file);
|
||||
generationItems.add(item);
|
||||
}
|
||||
}
|
||||
@@ -181,7 +178,7 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
return VfsUtil.toVirtualFileArray(set);
|
||||
}
|
||||
|
||||
public GenerationItem[] generate(CompileContext context, GenerationItem[] itemsToGenerate, VirtualFile outputRootDirectory) {
|
||||
public GenerationItem[] generate(GenerationItem[] itemsToGenerate, VirtualFile outputRootDirectory) {
|
||||
List<GenerationItem> generatedItems = new ArrayList<GenerationItem>();
|
||||
Map<String, GenerationItem> pathsToItemsMap = new HashMap<String, GenerationItem>();
|
||||
|
||||
@@ -192,7 +189,7 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
|
||||
Set<VirtualFile> vFiles = new HashSet<VirtualFile>();
|
||||
for (GenerationItem item : itemsToGenerate) {
|
||||
vFiles.add(((GenerationItemImpl) item).getVFile());
|
||||
vFiles.add(item.getVFile());
|
||||
}
|
||||
|
||||
for (VirtualFile vFile : vFiles) {
|
||||
@@ -270,19 +267,19 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
!classNames.contains(StringUtil.decapitalize(fileDefinitionName))) {
|
||||
final PsiClass scriptClass = file.getScriptClass();
|
||||
if (scriptClass != null) {
|
||||
generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, file, scriptClass, packageDefinition));
|
||||
generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, scriptClass, packageDefinition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final GrTypeDefinition typeDefinition : file.getTypeDefinitions()) {
|
||||
generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, file, typeDefinition, packageDefinition));
|
||||
generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, typeDefinition, packageDefinition));
|
||||
}
|
||||
|
||||
return generatedItemsRelativePaths;
|
||||
}
|
||||
|
||||
private static String getJavaClassPackage(GrPackageDefinition packageDefinition) {
|
||||
private static String getJavaClassPackage(@Nullable GrPackageDefinition packageDefinition) {
|
||||
if (packageDefinition == null) return "";
|
||||
|
||||
String prefix = packageDefinition.getPackageName();
|
||||
@@ -292,24 +289,43 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
return prefix;
|
||||
}
|
||||
|
||||
private String createJavaSourceFile(VirtualFile outputRootDirectory, GroovyFileBase file, @NotNull PsiClass typeDefinition, GrPackageDefinition packageDefinition) {
|
||||
//prefix defines structure of directories tree
|
||||
String prefix = "";
|
||||
if (packageDefinition != null) {
|
||||
prefix = getJavaClassPackage(packageDefinition);
|
||||
private String createJavaSourceFile(VirtualFile outputRootDirectory, @NotNull PsiClass typeDefinition, GrPackageDefinition packageDefinition) {
|
||||
StringBuffer text = new StringBuffer();
|
||||
writeTypeDefinition(text, typeDefinition, packageDefinition, true);
|
||||
|
||||
String prefix = getJavaClassPackage(packageDefinition);
|
||||
String outputDir = outputRootDirectory.getPath();
|
||||
String fileName = typeDefinition.getName() + "." + "java";
|
||||
|
||||
String prefixWithoutSeparator = prefix;
|
||||
|
||||
if (!"".equals(prefix)) {
|
||||
prefixWithoutSeparator = prefix.substring(0, prefix.length() - PREFIX_SEPARATOR.length());
|
||||
new File(outputDir, prefixWithoutSeparator).mkdirs();
|
||||
}
|
||||
|
||||
StringBuffer text = new StringBuffer();
|
||||
File myFile;
|
||||
if (!"".equals(prefix))
|
||||
myFile = new File(outputDir + File.separator + prefixWithoutSeparator, fileName);
|
||||
else
|
||||
myFile = new File(outputDir, fileName);
|
||||
|
||||
final String typeDefinitionName = typeDefinition.getName();
|
||||
writeTypeDefinition(text, typeDefinitionName, typeDefinition, packageDefinition);
|
||||
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
assert virtualFile != null;
|
||||
// String generatedFileRelativePath = prefix + typeDefinitionName + "." + "java";
|
||||
String fileShortName = typeDefinitionName + "." + "java";
|
||||
createGeneratedFile(text, outputRootDirectory.getPath(), prefix, fileShortName);
|
||||
return prefix + typeDefinitionName + "." + "java";
|
||||
BufferedWriter writer = null;
|
||||
try {
|
||||
Writer fileWriter = new FileWriter(myFile);
|
||||
writer = new BufferedWriter(fileWriter);
|
||||
writer.write(text.toString());
|
||||
} catch (IOException e) {
|
||||
LOG.error(e);
|
||||
} finally {
|
||||
try {
|
||||
assert writer != null;
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
return prefix + fileName;
|
||||
}
|
||||
|
||||
private static GrTopStatement[] getTopStatementsInReadAction(final GroovyFileBase myPsiFile) {
|
||||
@@ -333,7 +349,8 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
return isOnlyInnerTypeDef;
|
||||
}
|
||||
|
||||
private void writeTypeDefinition(StringBuffer text, String typeDefinitionName, @NotNull PsiClass typeDefinition, GrPackageDefinition packageDefinition) {
|
||||
private void writeTypeDefinition(StringBuffer text, @NotNull PsiClass typeDefinition,
|
||||
@Nullable GrPackageDefinition packageDefinition, boolean toplevel) {
|
||||
final boolean isScript = typeDefinition instanceof GroovyScriptClass;
|
||||
|
||||
writePackageStatement(text, packageDefinition);
|
||||
@@ -345,39 +362,26 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
boolean isEnum = typeDefinition instanceof GrEnumTypeDefinition;
|
||||
boolean isAtInterface = typeDefinition instanceof GrAnnotationTypeDefinition;
|
||||
|
||||
|
||||
PsiModifierList modifierList = typeDefinition.getModifierList();
|
||||
|
||||
boolean wasAddedModifiers = modifierList != null && writeTypeDefinitionMethodModifiers(text, modifierList, JAVA_TYPE_DEFINITION_MODIFIERS, typeDefinition.isInterface());
|
||||
if (!wasAddedModifiers) {
|
||||
text.append("public ");
|
||||
}
|
||||
writeClassModifiers(text, typeDefinition.getModifierList(), typeDefinition.isInterface(), toplevel);
|
||||
|
||||
if (isInterface) text.append("interface");
|
||||
else if (isEnum) text.append("enum");
|
||||
else if (isAtInterface) text.append("@interface");
|
||||
else text.append("class");
|
||||
|
||||
text.append(" ");
|
||||
text.append(" ").append(typeDefinition.getName());
|
||||
|
||||
text.append(typeDefinitionName);
|
||||
|
||||
if (typeDefinition != null) {
|
||||
appendTypeParameters(text, typeDefinition);
|
||||
}
|
||||
appendTypeParameters(text, typeDefinition);
|
||||
|
||||
text.append(" ");
|
||||
|
||||
if (isScript) {
|
||||
text.append("extends ");
|
||||
text.append("groovy.lang.Script ");
|
||||
text.append("extends groovy.lang.Script ");
|
||||
} else if (!isEnum && !isAtInterface) {
|
||||
final PsiClassType[] extendsClassesTypes = typeDefinition.getExtendsListTypes();
|
||||
|
||||
if (extendsClassesTypes.length > 0) {
|
||||
text.append("extends ");
|
||||
text.append(computeTypeText(extendsClassesTypes[0], false));
|
||||
text.append(" ");
|
||||
text.append("extends ").append(computeTypeText(extendsClassesTypes[0], false)).append(" ");
|
||||
}
|
||||
PsiClassType[] implementsTypes = typeDefinition.getImplementsListTypes();
|
||||
|
||||
@@ -386,8 +390,7 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
int i = 0;
|
||||
while (i < implementsTypes.length) {
|
||||
if (i > 0) text.append(", ");
|
||||
text.append(computeTypeText(implementsTypes[i], false));
|
||||
text.append(" ");
|
||||
text.append(computeTypeText(implementsTypes[i], false)).append(" ");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -457,6 +460,10 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
writeVariableDeclarations(text, (GrVariableDeclaration) declaration);
|
||||
}
|
||||
}
|
||||
for (PsiClass inner : typeDefinition.getInnerClasses()) {
|
||||
writeTypeDefinition(text, inner, null, false);
|
||||
text.append("\n");
|
||||
}
|
||||
|
||||
text.append("}");
|
||||
}
|
||||
@@ -527,7 +534,7 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
}
|
||||
}
|
||||
|
||||
private void writeConstructor(final StringBuffer text, final GrConstructor constructor, boolean isEnum) {
|
||||
private static void writeConstructor(final StringBuffer text, final GrConstructor constructor, boolean isEnum) {
|
||||
text.append("\n");
|
||||
text.append(" ");
|
||||
if (!isEnum) {
|
||||
@@ -543,23 +550,16 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
GrParameter[] parameterList = constructor.getParameters();
|
||||
|
||||
text.append("(");
|
||||
String paramType;
|
||||
GrTypeElement paramTypeElement;
|
||||
|
||||
for (int i = 0; i < parameterList.length; i++) {
|
||||
if (i > 0) text.append(", ");
|
||||
|
||||
GrParameter parameter = parameterList[i];
|
||||
paramTypeElement = parameter.getTypeElementGroovy();
|
||||
paramType = getTypeText(paramTypeElement);
|
||||
|
||||
text.append(paramType);
|
||||
text.append(" ");
|
||||
text.append(parameter.getName());
|
||||
text.append(getTypeText(parameter.getTypeElementGroovy())).append(" ").append(parameter.getName());
|
||||
}
|
||||
|
||||
text.append(")");
|
||||
text.append(" ");
|
||||
text.append(") ");
|
||||
|
||||
/************* body **********/
|
||||
|
||||
@@ -744,27 +744,32 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean writeTypeDefinitionMethodModifiers(StringBuffer text, PsiModifierList modifierList, String[] modifiers, boolean isInterface) {
|
||||
boolean wasAddedModifiers = false;
|
||||
for (String modifierType : modifiers) {
|
||||
if (modifierList.hasModifierProperty(modifierType)) {
|
||||
if (PsiModifier.ABSTRACT.equals(modifierType) && isInterface) {
|
||||
continue;
|
||||
private static void writeClassModifiers(StringBuffer text,
|
||||
@Nullable PsiModifierList modifierList, boolean isInterface, boolean toplevel) {
|
||||
if (modifierList == null || modifierList.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
text.append("public ");
|
||||
}
|
||||
|
||||
if (modifierList != null) {
|
||||
List<String> allowedModifiers = new ArrayList<String>();
|
||||
allowedModifiers.add(PsiModifier.FINAL);
|
||||
if (!toplevel) {
|
||||
allowedModifiers.addAll(Arrays.asList(PsiModifier.PROTECTED, PsiModifier.PRIVATE, PsiModifier.STATIC));
|
||||
}
|
||||
if (!isInterface) {
|
||||
allowedModifiers.add(PsiModifier.ABSTRACT);
|
||||
}
|
||||
|
||||
for (String modifierType : allowedModifiers) {
|
||||
if (modifierList.hasModifierProperty(modifierType)) {
|
||||
text.append(modifierType).append(" ");
|
||||
}
|
||||
text.append(modifierType);
|
||||
text.append(" ");
|
||||
wasAddedModifiers = true;
|
||||
}
|
||||
}
|
||||
return wasAddedModifiers;
|
||||
}
|
||||
|
||||
private static String getTypeText(GrTypeElement typeElement) {
|
||||
if (typeElement == null) {
|
||||
return "java.lang.Object";
|
||||
} else {
|
||||
return computeTypeText(typeElement.getType(), false);
|
||||
}
|
||||
return getTypeText(typeElement == null ? null : typeElement.getType(), false);
|
||||
}
|
||||
|
||||
private static String getTypeText(PsiType type, boolean allowVarargs) {
|
||||
@@ -786,66 +791,16 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
return canonicalText != null ? canonicalText : type.getPresentableText();
|
||||
}
|
||||
|
||||
private static void createGeneratedFile(StringBuffer text, String outputDir, String prefix, String generatedItemPath) {
|
||||
assert prefix != null;
|
||||
|
||||
String prefixWithoutSeparator = prefix;
|
||||
|
||||
if (!"".equals(prefix)) {
|
||||
prefixWithoutSeparator = prefix.substring(0, prefix.length() - PREFIX_SEPARATOR.length());
|
||||
new File(outputDir, prefixWithoutSeparator).mkdirs();
|
||||
}
|
||||
|
||||
File myFile;
|
||||
if (!"".equals(prefix))
|
||||
myFile = new File(outputDir + File.separator + prefixWithoutSeparator, generatedItemPath);
|
||||
else
|
||||
myFile = new File(outputDir, generatedItemPath);
|
||||
|
||||
BufferedWriter writer = null;
|
||||
try {
|
||||
Writer fileWriter = new FileWriter(myFile);
|
||||
writer = new BufferedWriter(fileWriter);
|
||||
writer.write(text.toString());
|
||||
} catch (IOException e) {
|
||||
LOG.error(e);
|
||||
} finally {
|
||||
try {
|
||||
assert writer != null;
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return "Groovy to java source code generator";
|
||||
}
|
||||
|
||||
public boolean validateConfiguration(CompileScope scope) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CharTrie myTrie = new CharTrie();
|
||||
|
||||
public void compilationFinished(boolean aborted, int errors, int warnings, final CompileContext compileContext) {
|
||||
myTrie.clear();
|
||||
}
|
||||
|
||||
public ValidityState createValidityState(DataInput in) throws IOException {
|
||||
return TimestampValidityState.load(in);
|
||||
}
|
||||
|
||||
class GenerationItemImpl implements GenerationItem {
|
||||
public class GenerationItem {
|
||||
ValidityState myState;
|
||||
private final boolean myInTestSources;
|
||||
final Module myModule;
|
||||
public int myHashCode;
|
||||
private final VirtualFile myVFile;
|
||||
|
||||
public GenerationItemImpl(String path, Module module, ValidityState state, boolean isInTestSources, VirtualFile vFile) {
|
||||
public GenerationItem(String path, Module module, ValidityState state, boolean isInTestSources, VirtualFile vFile) {
|
||||
myVFile = vFile;
|
||||
myModule = module;
|
||||
myState = state;
|
||||
@@ -857,18 +812,10 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat
|
||||
return myTrie.getString(myHashCode);
|
||||
}
|
||||
|
||||
public ValidityState getValidityState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
public Module getModule() {
|
||||
return myModule;
|
||||
}
|
||||
|
||||
public boolean isTestSource() {
|
||||
return myInTestSources;
|
||||
}
|
||||
|
||||
public VirtualFile getVFile() {
|
||||
return myVFile;
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ public class GroovyCompilerTest extends GroovyCompilerTestCase {
|
||||
|
||||
Module dep = addDependentModule();
|
||||
|
||||
addGroovyLibrary(dep);
|
||||
addGroovyLibrary(dep, false);
|
||||
|
||||
assertEmpty(make());
|
||||
assertOutput("Bar", "239", dep);
|
||||
@@ -278,5 +278,14 @@ public class GroovyCompilerTest extends GroovyCompilerTestCase {
|
||||
assertEmpty make()
|
||||
}
|
||||
|
||||
public void test1_7InnerClass() throws Exception {
|
||||
myFixture.addFileToProject "Foo.groovy", """
|
||||
class Foo {
|
||||
static class Bar {}
|
||||
}"""
|
||||
myFixture.addFileToProject "AJava.java", "public class AJava extends Foo.Bar {}"
|
||||
assertEmpty make()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.intellij.util.concurrency.Semaphore;
|
||||
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerLoader;
|
||||
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
|
||||
import org.jetbrains.plugins.groovy.util.GroovyUtils;
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -65,7 +66,7 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
|
||||
|
||||
CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(myMainOutput.findOrCreateDir("out").getUrl());
|
||||
|
||||
addGroovyLibrary(myModule);
|
||||
addGroovyLibrary(myModule, getName().contains("1_7"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,8 +75,8 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
|
||||
super.tuneFixture(moduleBuilder);
|
||||
}
|
||||
|
||||
protected static void addGroovyLibrary(final Module to) {
|
||||
final String root = PathManager.getHomePath() + "/community/lib/";
|
||||
protected static void addGroovyLibrary(final Module to, boolean version17) {
|
||||
final String root = version17 ? TestUtils.getRealGroovy1_7LibraryHome() : PathManager.getHomePath() + "/community/lib/";
|
||||
final File[] groovyJars = GroovyUtils.getFilesInDirectoryByPattern(root, GroovyConfigUtils.GROOVY_ALL_JAR_PATTERN);
|
||||
assert groovyJars.length == 1;
|
||||
PsiTestUtil.addLibrary(to, "groovy", root, groovyJars[0].getName());
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package org.jetbrains.plugins.groovy.lang.generator;
|
||||
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.compiler.GeneratingCompiler;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import com.intellij.testFramework.fixtures.TempDirTestFixture;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.plugins.groovy.compiler.generator.GroovyToJavaGenerator;
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils;
|
||||
@@ -77,15 +76,15 @@ public void testArrayType1() throws Throwable { doTest(); }
|
||||
|
||||
final StringBuffer buffer = new StringBuffer();
|
||||
final GroovyToJavaGeneratorTester groovyToJavaGeneratorTester = new GroovyToJavaGeneratorTester(relTestPath, data.get(0), getProject());
|
||||
final GeneratingCompiler.GenerationItem[][] generatedItems = new GeneratingCompiler.GenerationItem[1][1];
|
||||
final GroovyToJavaGenerator.GenerationItem[][] generatedItems = new GroovyToJavaGenerator.GenerationItem[1][1];
|
||||
|
||||
GeneratingCompiler.GenerationItem[] generationItems = groovyToJavaGeneratorTester.getGenerationItems(null);
|
||||
GroovyToJavaGenerator.GenerationItem[] generationItems = groovyToJavaGeneratorTester.getGenerationItems(null);
|
||||
|
||||
VirtualFile outputDirVirtualFile = tempDirFixture.getFile("");
|
||||
|
||||
generatedItems[0] = groovyToJavaGeneratorTester.generate(null, generationItems, outputDirVirtualFile);
|
||||
generatedItems[0] = groovyToJavaGeneratorTester.generate(generationItems, outputDirVirtualFile);
|
||||
|
||||
for (GeneratingCompiler.GenerationItem generatedItem : generatedItems[0]) {
|
||||
for (GroovyToJavaGenerator.GenerationItem generatedItem : generatedItems[0]) {
|
||||
final String path = tempDirFixture.getTempDirPath() + File.separator + generatedItem.getPath();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new FileReader(path));
|
||||
|
||||
@@ -58,6 +58,10 @@ public abstract class TestUtils {
|
||||
return getAbsoluteTestDataPath() + "/mockGroovyLib1.7";
|
||||
}
|
||||
|
||||
public static String getRealGroovy1_7LibraryHome() {
|
||||
return getAbsoluteTestDataPath() + "/realGroovy17/";
|
||||
}
|
||||
|
||||
public static String getMockGroovy1_7LibraryName() {
|
||||
return getMockGroovy1_7LibraryHome()+"/groovy-all-1.7.jar";
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -16,6 +16,7 @@
|
||||
package com.intellij.html.impl;
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.xml.XmlAttributeDescriptor;
|
||||
@@ -82,6 +83,11 @@ public class RelaxedHtmlFromSchemaElementDescriptor extends XmlElementDescriptor
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute) {
|
||||
return getAttributeDescriptor(attribute.getName(), attribute.getParent());
|
||||
}
|
||||
|
||||
public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context) {
|
||||
final XmlAttributeDescriptor descriptor = super.getAttributeDescriptor(attributeName.toLowerCase(), context);
|
||||
if (descriptor != null) return descriptor;
|
||||
|
||||
@@ -156,15 +156,17 @@ public class XmlElementDescriptorImpl implements XmlElementDescriptor, PsiWritab
|
||||
return nsDescriptor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TypeDescriptor getType() {
|
||||
return getType(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TypeDescriptor getType(XmlElement context) {
|
||||
final XmlNSDescriptor nsDescriptor = getNSDescriptor(context);
|
||||
if (!(nsDescriptor instanceof XmlNSDescriptorImpl)) return null;
|
||||
if (!(nsDescriptor instanceof XmlNSTypeDescriptorProvider)) return null;
|
||||
|
||||
TypeDescriptor type = ((XmlNSDescriptorImpl) nsDescriptor).getTypeDescriptor(myDescriptorTag);
|
||||
TypeDescriptor type = ((XmlNSTypeDescriptorProvider) nsDescriptor).getTypeDescriptor(myDescriptorTag);
|
||||
if (type == null) {
|
||||
String substAttr = myDescriptorTag.getAttributeValue("substitutionGroup");
|
||||
if (substAttr != null) {
|
||||
|
||||
@@ -48,7 +48,7 @@ import java.util.*;
|
||||
* @author Mike
|
||||
*/
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public class XmlNSDescriptorImpl implements XmlNSDescriptor,Validator<XmlDocument>, DumbAware {
|
||||
public class XmlNSDescriptorImpl implements XmlNSDescriptor,Validator<XmlDocument>, DumbAware, XmlNSTypeDescriptorProvider {
|
||||
@NonNls private static final Set<String> STD_TYPES = new HashSet<String>();
|
||||
private static final Set<String> UNDECLARED_STD_TYPES = new HashSet<String>();
|
||||
private XmlFile myFile;
|
||||
@@ -335,7 +335,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptor,Validator<XmlDocumen
|
||||
return new XmlAttributeDescriptorImpl(tag);
|
||||
}
|
||||
|
||||
protected TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) {
|
||||
public TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) {
|
||||
String type = descriptorTag.getAttributeValue("type");
|
||||
|
||||
if (type != null) {
|
||||
@@ -405,20 +405,23 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptor,Validator<XmlDocumen
|
||||
return defaultNSDescriptor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected TypeDescriptor findTypeDescriptor(final String qname) {
|
||||
return findTypeDescriptor(qname, myTag);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected TypeDescriptor findTypeDescriptor(final String qname, XmlTag context) {
|
||||
String namespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(qname));
|
||||
return findTypeDescriptor(XmlUtil.findLocalNameByQualifiedName(qname), namespace);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TypeDescriptor findTypeDescriptor(String localName, String namespace) {
|
||||
TypeDescriptor typeDescriptor = findTypeDescriptorImpl(myTag, localName, namespace, null);
|
||||
return typeDescriptor;
|
||||
return findTypeDescriptorImpl(myTag, localName, namespace, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected TypeDescriptor findTypeDescriptorImpl(XmlTag rootTag, final String name, String namespace, Set<XmlTag> visited) {
|
||||
XmlNSDescriptorImpl responsibleDescriptor = this;
|
||||
if (namespace != null && namespace.length() != 0 && !namespace.equals(getDefaultNamespace())) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.xml.impl.schema;
|
||||
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public interface XmlNSTypeDescriptorProvider {
|
||||
@Nullable
|
||||
TypeDescriptor getTypeDescriptor(String name, XmlTag context);
|
||||
|
||||
@Nullable
|
||||
TypeDescriptor getTypeDescriptor(XmlTag descriptorTag);
|
||||
}
|
||||
@@ -38,7 +38,7 @@ import java.util.Map;
|
||||
public class XmlNamespaceIndex extends XmlIndex<String> {
|
||||
|
||||
@Nullable
|
||||
public static String getNamespace(VirtualFile file, final Project project) {
|
||||
public static String getNamespace(@NotNull VirtualFile file, final Project project) {
|
||||
final List<String> list = FileBasedIndex.getInstance().getValues(NAME, file.getUrl(), createFilter(project));
|
||||
return list.size() == 0 ? null : list.get(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user