Merge branch 'master' of github.com:JetBrains/kotlin

This commit is contained in:
James Strachan
2012-02-29 13:59:34 +00:00
135 changed files with 1634 additions and 1036 deletions
+1
View File
@@ -6,6 +6,7 @@ confluence/target
out
dist
ideaSDK
PluginVerifier
.idea/dictionaries/yozh.xml
.idea/codeStyleSettings.xml
.idea/workspace.xml
+4
View File
@@ -49,6 +49,10 @@
<inspection_tool class="ContinueOrBreakFromFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CovariantCompareTo" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CovariantEquals" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="DeclareCollectionAsInterface" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoreLocalVariables" value="false" />
<option name="ignorePrivateMethodsAndFields" value="false" />
</inspection_tool>
<inspection_tool class="DoubleCheckedLocking" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoreOnVolatileVariables" value="true" />
</inspection_tool>
+1 -1
View File
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="asm">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/asm-util-3.3.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/asm-all-3.3.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
+3
View File
@@ -3,6 +3,9 @@
<CLASSES>
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/js.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/dartc.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/args4j-2.0.12.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/guava-10.0.1.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/json.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
+33
View File
@@ -0,0 +1,33 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Js-backend tests" type="JUnit" factoryName="JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="js.tests" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" value="" />
<option name="PACKAGE_NAME" value="org.jetbrains.k2js.test" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/js" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<envs />
<patterns />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="" />
<option name="TRANSPORT" value="0" />
<option name="LOCAL" value="true" />
</RunnerSettings>
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Debug" />
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="AntTarget" enabled="false" antfile="file://$PROJECT_DIR$/js_backend_tests.xml" target="copy_lib" />
</method>
</configuration>
</component>
+16 -2
View File
@@ -2,10 +2,15 @@
<import file="build.xml" optional="false"/>
<property name="build.number" value="snapshot"/>
<property name="jdk16.home" value="${java.home}"/>
<property name="artifact.output.path" value="${basedir}/out/artifacts"/>
<property name="plugin.xml" value="idea/src/META-INF/plugin.xml"/>
<property name="plugin.xml.bk" value="${plugin.xml}.bk"/>
<property name="plugin.verifier" value="${basedir}/PluginVerifier/plugin-verifier-1.0-SNAPSHOT.jar"/>
<property name="plugin.zip" value="${artifact.output.path}/kotlin-plugin-${build.number}.zip" />
<macrodef name="echoprop">
<attribute name="prop"/>
<sequential>
@@ -55,13 +60,22 @@
</target>
<target name="zipArtifact">
<zip destfile="${artifact.output.path}/kotlin-plugin-${build.number}.zip">
<zip destfile="${plugin.zip}">
<zipfileset prefix="Kotlin" dir="${artifact.output.path}/Kotlin"/>
</zip>
<delete dir="${artifact.output.path}/Kotlin" quiet="true"/>
</target>
<target name="post_build" depends="cleanupPluginXml, zipArtifact"/>
<target name="verifyPlugin">
<java fork="true" failonerror="true" jar="${plugin.verifier}">
<arg value="-r" />
<arg value="${jdk16.home}" />
<arg value="${plugin.zip}" />
<arg value="${basedir}/ideaSDK" />
</java>
</target>
<target name="post_build" depends="cleanupPluginXml, zipArtifact, verifyPlugin"/>
<target name="none">
<fail message="Either specify pre_build or post_build"/>
@@ -25,29 +25,21 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.RECEIVER;
/**
* @author Nikolay Krasko, Alefas
*/
@@ -146,7 +138,9 @@ public final class TipsManager {
return false;
}
for (ReceiverDescriptor receiverDescriptor : result) {
if (checkReceiverResolution(receiverDescriptor, callableDescriptor)) return false;
if (ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, callableDescriptor)) {
return false;
}
}
return true;
}
@@ -183,51 +177,10 @@ public final class TipsManager {
new Predicate<CallableDescriptor>() {
@Override
public boolean apply(CallableDescriptor callableDescriptor) {
return checkReceiverResolution(receiverDescriptor, callableDescriptor);
return ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, callableDescriptor);
}
}));
return descriptorsSet;
}
/*
* Checks if receiver declaration could be resolved to call expected receiver.
*/
private static boolean checkReceiverResolution (
@NotNull ReceiverDescriptor expectedReceiver,
@NotNull CallableDescriptor receiverArgument
) {
JetType type = expectedReceiver.getType();
if (checkReceiverResolution(expectedReceiver, type, receiverArgument)) return true;
if (type.isNullable()) {
JetType notNullableType = TypeUtils.makeNotNullable(type);
if (checkReceiverResolution(expectedReceiver, notNullableType, receiverArgument)) return true;
}
return false;
}
private static boolean checkReceiverResolution (
@NotNull ReceiverDescriptor expectedReceiver,
@NotNull JetType receiverType,
@NotNull CallableDescriptor receiverArgument
) {
ConstraintSystem constraintSystem = new ConstraintSystemImpl(ConstraintResolutionListener.DO_NOTHING);
for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) {
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT);
}
ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter();
if (expectedReceiver.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(
RECEIVER.assertSubtyping(receiverType, receiverParameter.getType()));
}
else if (expectedReceiver.exists() || receiverParameter.exists()) {
// Only one of receivers exist
return false;
}
ConstraintSystemSolution solution = constraintSystem.solve();
return solution.getStatus().isSuccessful();
}
}
@@ -19,12 +19,8 @@ package org.jetbrains.jet.cli;
import com.sampullara.cli.Args;
import com.sampullara.cli.Argument;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.compiler.CompileEnvironment;
import org.jetbrains.jet.compiler.CompileEnvironmentException;
import org.jetbrains.jet.compiler.CompilerPlugin;
import org.jetbrains.jet.compiler.FileNameTransformer;
import org.jetbrains.jet.compiler.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
/**
@@ -72,6 +68,9 @@ public class KotlinCompiler {
@Argument(value = "stubs", description = "Compile stubs: ignore function bodies")
public boolean stubs;
@Argument(value = "tags", description = "Demarcate each compilation message (error, warning, etc) with an open and close tag")
public boolean tags;
@Argument(value = "transformNamesToJava", description = "Transform Kotlin file names to *.java. This option is needed for compiling kotlinized Java library headers")
public boolean transformNamesToJava;
}
@@ -108,7 +107,8 @@ public class KotlinCompiler {
return 1;
}
catch (Throwable t) {
t.printStackTrace();
// Always use tags
errStream.println(MessageRenderer.TAGS.renderException(t));
return 1;
}
@@ -117,7 +117,11 @@ public class KotlinCompiler {
return 0;
}
CompileEnvironment environment = new CompileEnvironment(arguments.transformNamesToJava ? ANY_EXTENSION_TO_JAVA : FileNameTransformer.IDENTITY);
FileNameTransformer fileNameTransformer = arguments.transformNamesToJava
? ANY_EXTENSION_TO_JAVA
: FileNameTransformer.IDENTITY;
MessageRenderer messageRenderer = arguments.tags ? MessageRenderer.TAGS : MessageRenderer.PLAIN;
CompileEnvironment environment = new CompileEnvironment(fileNameTransformer, messageRenderer);
try {
environment.setIgnoreErrors(false);
environment.setErrorStream(errStream);
@@ -138,16 +142,18 @@ public class KotlinCompiler {
if (arguments.module != null) {
environment.compileModuleScript(arguments.module, arguments.jar, arguments.outputDir, arguments.includeRuntime);
return 0;
}
else {
if (!environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime)) {
return 1;
}
environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime);
}
return 0;
} finally {
}
catch (Throwable t) {
errStream.println(messageRenderer.renderException(t));
return 1;
}
finally {
environment.dispose();
}
}
@@ -55,7 +55,9 @@ import java.util.jar.*;
public class CompileEnvironment {
private JetCoreEnvironment myEnvironment;
private final Disposable myRootDisposable;
private PrintStream myErrorStream = System.out;
private final MessageRenderer myMessageRenderer;
private PrintStream myErrorStream = System.err;
private final FileNameTransformer myFileNameTransformer;
private URL myStdlib;
@@ -63,10 +65,10 @@ public class CompileEnvironment {
private boolean stubs = false;
public CompileEnvironment() {
this(FileNameTransformer.IDENTITY);
this(FileNameTransformer.IDENTITY, MessageRenderer.PLAIN);
}
public CompileEnvironment(FileNameTransformer fileNameTransformer) {
public CompileEnvironment(FileNameTransformer fileNameTransformer, MessageRenderer messageRenderer) {
myRootDisposable = new Disposable() {
@Override
public void dispose() {
@@ -74,6 +76,7 @@ public class CompileEnvironment {
};
myEnvironment = new JetCoreEnvironment(myRootDisposable);
myFileNameTransformer = fileNameTransformer;
myMessageRenderer = messageRenderer;
}
public void setErrorStream(PrintStream errorStream) {
@@ -145,7 +148,7 @@ public class CompileEnvironment {
File rtJar = findRtJar(javaHome);
if (rtJar == null || !rtJar.exists()) {
throw new CompileEnvironmentException("No JDK rt.jar found under" + javaHome);
throw new CompileEnvironmentException("No JDK rt.jar found under " + javaHome);
}
return rtJar;
@@ -164,8 +167,8 @@ public class CompileEnvironment {
return null;
}
public void compileModuleScript(String moduleFile, @Nullable String jarPath, @Nullable String outputDir, boolean jarRuntime) {
final List<Module> modules = loadModuleScript(moduleFile);
public boolean compileModuleScript(String moduleFile, @Nullable String jarPath, @Nullable String outputDir, boolean jarRuntime) {
List<Module> modules = loadModuleScript(moduleFile);
if (modules == null) {
throw new CompileEnvironmentException("Module script " + moduleFile + " compilation failed");
@@ -178,20 +181,22 @@ public class CompileEnvironment {
final String directory = new File(moduleFile).getParent();
for (Module moduleBuilder : modules) {
ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory);
if (moduleFactory != null) {
if (outputDir != null) {
writeToOutputDirectory(moduleFactory, outputDir);
}
else {
String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath();
try {
writeToJar(moduleFactory, new FileOutputStream(path), null, jarRuntime);
} catch (FileNotFoundException e) {
throw new CompileEnvironmentException("Invalid jar path " + path, e);
}
if (moduleFactory == null) {
return false;
}
if (outputDir != null) {
writeToOutputDirectory(moduleFactory, outputDir);
}
else {
String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath();
try {
writeToJar(moduleFactory, new FileOutputStream(path), null, jarRuntime);
} catch (FileNotFoundException e) {
throw new CompileEnvironmentException("Invalid jar path " + path, e);
}
}
}
return true;
}
public List<Module> loadModuleScript(String moduleFile) {
@@ -199,7 +204,7 @@ public class CompileEnvironment {
scriptCompileSession.addSources(moduleFile);
ensureRuntime();
if (!scriptCompileSession.analyze(myErrorStream)) {
if (!scriptCompileSession.analyze(myErrorStream, myMessageRenderer)) {
return null;
}
final ClassFileFactory factory = scriptCompileSession.generate();
@@ -258,7 +263,7 @@ public class CompileEnvironment {
ensureRuntime();
if (!moduleCompileSession.analyze(myErrorStream) && !ignoreErrors) {
if (!moduleCompileSession.analyze(myErrorStream, myMessageRenderer) && !ignoreErrors) {
return null;
}
return moduleCompileSession.generate();
@@ -345,7 +350,7 @@ public class CompileEnvironment {
CompileSession session = new CompileSession(myEnvironment, myFileNameTransformer);
session.addSources(new LightVirtualFile("script" + LocalTimeCounter.currentTime() + ".kt", JetLanguage.INSTANCE, code));
if (!session.analyze(myErrorStream) && !ignoreErrors) {
if (!session.analyze(myErrorStream, myMessageRenderer) && !ignoreErrors) {
return null;
}
@@ -370,7 +375,7 @@ public class CompileEnvironment {
ensureRuntime();
if (!session.analyze(myErrorStream) && !ignoreErrors) {
if (!session.analyze(myErrorStream, myMessageRenderer) && !ignoreErrors) {
return false;
}
@@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -41,8 +42,7 @@ import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.plugin.JetFileType;
import java.io.File;
import java.io.PrintStream;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -84,11 +84,11 @@ public class CompileSession {
VirtualFile vFile = myEnvironment.getLocalFileSystem().findFileByPath(path);
if (vFile == null) {
myErrors.add("ERROR: File/directory not found: " + path);
myErrors.add("File/directory not found: " + path);
return;
}
if (!vFile.isDirectory() && vFile.getFileType() != JetFileType.INSTANCE) {
myErrors.add("ERROR: Not a Kotlin file: " + path);
myErrors.add("Not a Kotlin file: " + path);
return;
}
@@ -135,40 +135,26 @@ public class CompileSession {
return mySourceFiles;
}
public boolean analyze(final PrintStream out) {
if (!myErrors.isEmpty()) {
for (String error : myErrors) {
out.println(error);
}
return false;
public boolean analyze(@NotNull PrintStream out, @NotNull MessageRenderer renderer) {
MessageCollector collector = new MessageCollector(renderer);
for (String error : myErrors) {
collector.report(Severity.ERROR, error, null, -1, -1);
}
final ErrorCollector errorCollector = new ErrorCollector();
reportSyntaxErrors(collector);
analyzeAndReportSemanticErrors(collector);
reportSyntaxErrors(errorCollector);
analyzeAndReportSemanticErrors(errorCollector);
collector.printTo(out);
boolean hasIncompleteHierarchyErrors;
Collection<ClassDescriptor> incompletes = myBindingContext.getKeys(BindingContext.INCOMPLETE_HIERARCHY);
if (!incompletes.isEmpty()) {
out.println(Severity.ERROR + ":: The following classes have incomplete hierarchies:");
for (ClassDescriptor incomplete : incompletes) {
out.println(Severity.ERROR + ":: " + fqName(incomplete));
}
hasIncompleteHierarchyErrors = true;
} else {
hasIncompleteHierarchyErrors = false;
}
errorCollector.flushTo(out);
return !errorCollector.hasErrors() && !hasIncompleteHierarchyErrors;
return !collector.hasErrors();
}
/**
* @see JetTypeMapper#getFQName(DeclarationDescriptor)
* TODO possibly duplicates DescriptorUtils#getFQName(DeclarationDescriptor)
*/
private String fqName(ClassOrNamespaceDescriptor descriptor) {
private static String fqName(ClassOrNamespaceDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration == null || containingDeclaration instanceof ModuleDescriptor || containingDeclaration.getName().equals(JavaDescriptorResolver.JAVA_ROOT)) {
return descriptor.getName();
@@ -177,18 +163,31 @@ public class CompileSession {
}
}
private void analyzeAndReportSemanticErrors(ErrorCollector errorCollector) {
private void analyzeAndReportSemanticErrors(MessageCollector collector) {
Predicate<PsiFile> filesToAnalyzeCompletely =
stubs ? Predicates.<PsiFile>alwaysFalse() : Predicates.<PsiFile>alwaysTrue();
myBindingContext = AnalyzerFacade.analyzeFilesWithJavaIntegration(
myEnvironment.getProject(), mySourceFiles, filesToAnalyzeCompletely, JetControlFlowDataTraceFactory.EMPTY);
for (Diagnostic diagnostic : myBindingContext.getDiagnostics()) {
errorCollector.report(diagnostic);
reportDiagnostic(collector, diagnostic);
}
reportIncompleteHierarchies(collector);
}
private void reportIncompleteHierarchies(MessageCollector collector) {
Collection<ClassDescriptor> incompletes = myBindingContext.getKeys(BindingContext.INCOMPLETE_HIERARCHY);
if (!incompletes.isEmpty()) {
StringBuilder message = new StringBuilder("The following classes have incomplete hierarchies:\n");
for (ClassDescriptor incomplete : incompletes) {
message.append(" ").append(fqName(incomplete)).append("\n");
}
collector.report(Severity.ERROR, message.toString(), null, -1, -1);
}
}
private void reportSyntaxErrors(final ErrorCollector errorCollector) {
private void reportSyntaxErrors(final MessageCollector messageCollector) {
for (JetFile file : mySourceFiles) {
file.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
@@ -196,12 +195,19 @@ public class CompileSession {
String description = element.getErrorDescription();
String message = StringUtil.isEmpty(description) ? "Syntax error" : description;
Diagnostic diagnostic = DiagnosticFactory.create(Severity.ERROR, message).on(element);
errorCollector.report(diagnostic);
reportDiagnostic(messageCollector, diagnostic);
}
});
}
}
private static void reportDiagnostic(MessageCollector collector, Diagnostic diagnostic) {
DiagnosticUtils.LineAndColumn lineAndColumn = DiagnosticUtils.getLineAndColumn(diagnostic);
VirtualFile virtualFile = diagnostic.getPsiFile().getVirtualFile();
String path = virtualFile == null ? null : virtualFile.getPath();
collector.report(diagnostic.getSeverity(), diagnostic.getMessage(), path, lineAndColumn.getLine(), lineAndColumn.getColumn());
}
@NotNull
public ClassFileFactory generate() {
Project project = myEnvironment.getProject();
@@ -18,9 +18,8 @@ package org.jetbrains.jet.compiler;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.intellij.psi.PsiFile;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Severity;
import java.io.PrintStream;
@@ -29,27 +28,28 @@ import java.util.Collection;
/**
* @author alex.tkachman
*/
class ErrorCollector {
private final Multimap<PsiFile, Diagnostic> maps = LinkedHashMultimap.create();
/*package*/ class MessageCollector {
// File path (nullable) -> error message
private final Multimap<String, String> groupedMessages = LinkedHashMultimap.create();
private final MessageRenderer renderer;
private boolean hasErrors;
public ErrorCollector() {
public MessageCollector(@NotNull MessageRenderer renderer) {
this.renderer = renderer;
}
public void report(Diagnostic diagnostic) {
hasErrors |= diagnostic.getSeverity() == Severity.ERROR;
maps.put(diagnostic.getPsiFile(), diagnostic);
public void report(@NotNull Severity severity, @NotNull String message, @Nullable String path, int line, int column) {
hasErrors |= severity == Severity.ERROR;
groupedMessages.put(path, renderer.render(severity, message, path, line, column));
}
public void flushTo(final PrintStream out) {
if(!maps.isEmpty()) {
for (PsiFile psiFile : maps.keySet()) {
String path = psiFile.getVirtualFile().getPath();
Collection<Diagnostic> diagnostics = maps.get(psiFile);
for (Diagnostic diagnostic : diagnostics) {
String position = DiagnosticUtils.formatPosition(diagnostic);
out.println(diagnostic.getSeverity().toString() + ": " + path + ":" + position + " " + diagnostic.getMessage());
public void printTo(@NotNull PrintStream out) {
if (!groupedMessages.isEmpty()) {
for (String path : groupedMessages.keySet()) {
Collection<String> diagnostics = groupedMessages.get(path);
for (String diagnostic : diagnostics) {
out.println(diagnostic);
}
}
}
@@ -0,0 +1,76 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.compiler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Severity;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author abreslav
*/
public interface MessageRenderer {
MessageRenderer TAGS = new MessageRenderer() {
private String renderWithStringSeverity(String severityString, String message, String path, int line, int column) {
StringBuilder out = new StringBuilder();
out.append("<").append(severityString);
if (path != null) {
out.append(" path=\"").append(path).append("\"");
out.append(" line=\"").append(line).append("\"");
out.append(" column=\"").append(column).append("\"");
}
out.append(">\n");
out.append(message);
out.append("</").append(severityString).append(">\n");
return out.toString();
}
@Override
public String render(@NotNull Severity severity, @NotNull String message, @Nullable String path, int line, int column) {
return renderWithStringSeverity(severity.toString(), message, path, line, column);
}
@Override
public String renderException(@NotNull Throwable e) {
return renderWithStringSeverity("EXCEPTION", PLAIN.renderException(e), null, -1, -1);
}
};
MessageRenderer PLAIN = new MessageRenderer() {
@Override
public String render(@NotNull Severity severity, @NotNull String message, @Nullable String path, int line, int column) {
String position = path == null ? "" : path + ": (" + (line + ", " + column) + ") ";
return severity + ": " + position + message;
}
@Override
public String renderException(@NotNull Throwable e) {
StringWriter out = new StringWriter();
e.printStackTrace(new PrintWriter(out));
return out.toString();
}
};
String render(@NotNull Severity severity, @NotNull String message, @Nullable String path, int line, int column);
String renderException(@NotNull Throwable e);
}
@@ -419,7 +419,7 @@ public class JavaDescriptorResolver {
static void checkPsiClassIsNotJet(PsiClass psiClass) {
if (psiClass instanceof JetJavaMirrorMarker) {
throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass");
throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass: " + psiClass);
}
}
@@ -43,7 +43,7 @@ public class DiagnosticUtils {
if (element != null) {
return atLocation(element.getContainingFile(), element.getTextRange());
}
return "' at offset " + startOffset + " (line and file unknown)";
return "' at offset " + startOffset + " (line and file unknown: no PSI element)";
}
@Nullable
@@ -63,7 +63,7 @@ public class DiagnosticUtils {
@NotNull
public static String atLocation(@NotNull PsiFile file, @NotNull TextRange textRange) {
Document document = file.getViewProvider().getDocument();//PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
Document document = file.getViewProvider().getDocument();
return atLocation(file, textRange, document);
}
@@ -72,31 +72,28 @@ public class DiagnosticUtils {
int offset = textRange.getStartOffset();
VirtualFile virtualFile = file.getVirtualFile();
String pathSuffix = virtualFile == null ? "" : " in " + virtualFile.getPath();
if (document != null) {
int lineNumber = document.getLineNumber(offset);
int lineStartOffset = document.getLineStartOffset(lineNumber);
int column = offset - lineStartOffset;
return "' at line " + (lineNumber + 1) + ":" + (column + 1) + pathSuffix;
}
else {
return "' at offset " + offset + " (line unknown)" + pathSuffix;
}
return offsetToLineAndColumn(document, offset).toString() + pathSuffix;
}
public static String formatPosition(Diagnostic<PsiElement> diagnostic) {
@NotNull
public static LineAndColumn getLineAndColumn(@NotNull Diagnostic<? extends PsiElement> diagnostic) {
PsiFile file = diagnostic.getPsiFile();
Document document = file.getViewProvider().getDocument();
TextRange firstRange = diagnostic.getTextRanges().iterator().next();
int offset = firstRange.getStartOffset();
if (document != null) {
int lineNumber = document.getLineNumber(offset);
int lineStartOffset = document.getLineStartOffset(lineNumber);
int column = offset - lineStartOffset;
return offsetToLineAndColumn(document, firstRange.getStartOffset());
}
return "(" + (lineNumber + 1) + "," + (column + 1) + ")";
@NotNull
public static LineAndColumn offsetToLineAndColumn(Document document, int offset) {
if (document == null) {
return new LineAndColumn(-1, offset);
}
return "(offset: " + offset + " line unknown)";
int lineNumber = document.getLineNumber(offset);
int lineStartOffset = document.getLineStartOffset(lineNumber);
int column = offset - lineStartOffset;
return new LineAndColumn(lineNumber + 1, column + 1);
}
public static void throwIfRunningOnServer(Throwable e) {
@@ -111,4 +108,31 @@ public class DiagnosticUtils {
throw new RuntimeException(e);
}
}
public static final class LineAndColumn {
private final int line;
private final int column;
public LineAndColumn(int line, int column) {
this.line = line;
this.column = column;
}
public int getLine() {
return line;
}
public int getColumn() {
return column;
}
// NOTE: This method is used for presenting positions to the user
@Override
public String toString() {
if (line < 0) {
return "(offset: " + column + " line unknown)";
}
return "(" + line + "," + column + ")";
}
}
}
@@ -17,13 +17,13 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.CheckUtil;
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.Collection;
import java.util.HashSet;
@@ -37,6 +37,9 @@ public class JetPsiUtil {
public static final String NO_NAME_PROVIDED = "<no name provided>";
private JetPsiUtil() {
}
@Nullable
public static JetExpression deparenthesize(@NotNull JetExpression expression) {
if (expression instanceof JetBinaryExpressionWithTypeRHS) {
@@ -157,6 +160,32 @@ public class JetPsiUtil {
return jetClass.getName();
}
public static String getFQName(JetNamedFunction jetNamedFunction) {
String functionName = jetNamedFunction.getName();
if (functionName == null) {
return functionName;
}
@SuppressWarnings("unchecked")
PsiElement qualifiedElement = PsiTreeUtil.getParentOfType(
jetNamedFunction,
JetFile.class, JetClassOrObject.class, JetNamedFunction.class);
String firstPart = "";
if (qualifiedElement instanceof JetFile) {
firstPart = getFQName((JetFile) qualifiedElement);
}
else if (qualifiedElement instanceof JetClassOrObject) {
firstPart = getFQName((JetClassOrObject) qualifiedElement);
}
else if (qualifiedElement instanceof JetNamedFunction) {
firstPart = getFQName((JetNamedFunction) qualifiedElement);
}
return QualifiedNamesUtil.combine(firstPart, functionName);
}
@Nullable @JetElement.IfNotParsed
public static String getImportPath(JetImportDirective importDirective) {
final JetExpression importedReference = importDirective.getImportedReference();
@@ -68,7 +68,7 @@ public class ImportsResolver {
List<JetImportDirective> importDirectives = file.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) {
Collection<? extends DeclarationDescriptor> descriptors = importResolver.processImportReference(importDirective, namespaceScope, delayedImporter);
if (descriptors != null && descriptors.size() == 1) {
if (descriptors.size() == 1) {
resolvedDirectives.put(importDirective, descriptors.iterator().next());
}
}
@@ -144,14 +144,15 @@ public class ImportsResolver {
this.firstPhase = firstPhase;
}
@Nullable
@NotNull
public Collection<? extends DeclarationDescriptor> processImportReference(@NotNull JetImportDirective importDirective, @NotNull JetScope scope, @NotNull Importer importer) {
if (importDirective.isAbsoluteInRootNamespace()) {
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
return null;
return Collections.emptyList();
}
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference == null) return null;
if (importedReference == null) return Collections.emptyList();
Collection<? extends DeclarationDescriptor> descriptors;
if (importedReference instanceof JetQualifiedExpression) {
descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope);
@@ -163,19 +164,23 @@ public class ImportsResolver {
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
if (importDirective.isAllUnder()) {
if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression)) return null;
if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression)) {
return Collections.emptyList();
}
for (DeclarationDescriptor descriptor : descriptors) {
importer.addAllUnderImport(descriptor);
}
return null;
return Collections.emptyList();
}
String aliasName = getAliasName(importDirective);
if (aliasName == null) return null;
if (aliasName == null) return Collections.emptyList();
for (DeclarationDescriptor descriptor : descriptors) {
importer.addAliasImport(descriptor, aliasName);
}
return descriptors;
}
@@ -140,7 +140,9 @@ public class CallMaker {
}
}
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List<JetExpression> argumentExpressions) {
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverDescriptor explicitReceiver,
@Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression,
@NotNull List<JetExpression> argumentExpressions) {
List<ValueArgument> arguments = Lists.newArrayList();
for (JetExpression argumentExpression : argumentExpressions) {
arguments.add(makeValueArgument(argumentExpression, calleeExpression));
@@ -366,7 +366,11 @@ public class CallResolver {
if (callElement instanceof JetBinaryExpression) {
JetBinaryExpression binaryExpression = (JetBinaryExpression) callElement;
JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ? operationReference.getText() : OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ?
operationReference.getText() :
OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
JetExpression right = binaryExpression.getRight();
if (right != null) {
trace.report(UNSAFE_INFIX_CALL.on(reference, binaryExpression.getLeft().getText(), operationString, right.getText()));
@@ -433,6 +437,7 @@ public class CallResolver {
@NotNull ResolutionTask<D> task, @NotNull TracingStrategy tracing
) {
OverloadResolutionResultsImpl<D> results = performResolution(trace, scope, expectedType, task, tracing);
// If resolution fails, we should check for some of the following situations:
// class A {
// val foo = Bar() // The following is intended to be an anonymous initializer,
@@ -448,7 +453,8 @@ public class CallResolver {
// {...} // intended to be a returned from the outer literal
// }
// }
EnumSet<OverloadResolutionResults.Code> someFailed = EnumSet.of(OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES, OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
EnumSet<OverloadResolutionResults.Code> someFailed = EnumSet.of(OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES,
OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
if (someFailed.contains(results.getResultCode()) && !task.getCall().getFunctionLiteralArguments().isEmpty()) {
// We have some candidates that failed for some reason
// And we have a suspect: the function literal argument
@@ -658,7 +664,7 @@ public class CallResolver {
return results;
}
private JetType getEffectiveExpectedType(ValueParameterDescriptor valueParameterDescriptor) {
private static JetType getEffectiveExpectedType(ValueParameterDescriptor valueParameterDescriptor) {
JetType effectiveExpectedType = valueParameterDescriptor.getVarargElementType();
if (effectiveExpectedType == null) {
effectiveExpectedType = valueParameterDescriptor.getType();
@@ -666,7 +672,7 @@ public class CallResolver {
return effectiveExpectedType;
}
private void recordAutoCastIfNecessary(ReceiverDescriptor receiver, BindingTrace trace) {
private static void recordAutoCastIfNecessary(ReceiverDescriptor receiver, BindingTrace trace) {
if (receiver instanceof AutoCastReceiver) {
AutoCastReceiver autoCastReceiver = (AutoCastReceiver) receiver;
ReceiverDescriptor original = autoCastReceiver.getOriginal();
@@ -703,7 +709,9 @@ public class CallResolver {
}
}
private <D extends CallableDescriptor> void replaceValueParametersWithSubstitutedOnes(ResolvedCallImpl<D> candidateCall, @NotNull D substitutedDescriptor) {
private static <D extends CallableDescriptor> void replaceValueParametersWithSubstitutedOnes(
ResolvedCallImpl<D> candidateCall, @NotNull D substitutedDescriptor) {
Map<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap = Maps.newHashMap();
for (ValueParameterDescriptor valueParameterDescriptor : substitutedDescriptor.getValueParameters()) {
parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor);
@@ -726,7 +734,9 @@ public class CallResolver {
return result;
}
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(TracingStrategy tracing, ResolvedCallImpl<D> candidateCall, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument, ResolutionTask<D> task) {
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(TracingStrategy tracing, ResolvedCallImpl<D> candidateCall,
ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument,
ResolutionTask<D> task) {
ResolutionStatus result = SUCCESS;
if (receiverParameter.exists() && receiverArgument.exists()) {
ASTNode callOperationNode = task.getCall().getCallOperationNode();
@@ -841,6 +851,7 @@ public class CallResolver {
return OverloadResolutionResultsImpl.manyFailedCandidates(results.getResultingCalls());
}
}
assert false : "Should not be reachable, cause every status must belong to some level";
Set<ResolvedCallImpl<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
@@ -849,8 +860,10 @@ public class CallResolver {
tracing.recordAmbiguity(trace, noOverrides);
return OverloadResolutionResultsImpl.manyFailedCandidates(noOverrides);
}
failedCandidates = noOverrides;
}
ResolvedCallImpl<D> failed = failedCandidates.iterator().next();
failed.getTrace().commit();
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
@@ -861,7 +874,7 @@ public class CallResolver {
}
}
private <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallImpl<D>> results) {
private static <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallImpl<D>> results) {
for (ResolvedCallImpl<D> result : results) {
if (result.isDirty()) return false;
}
@@ -939,7 +952,8 @@ public class CallResolver {
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.<ResolvedCallImpl<FunctionDescriptor>>emptySet());
}
private List<ResolvedCallImpl<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, String name, List<JetType> parameterTypes) {
private List<ResolvedCallImpl<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver,
String name, List<JetType> parameterTypes) {
List<ResolvedCallImpl<FunctionDescriptor>> result = Lists.newArrayList();
if (receiver.exists()) {
Collection<ResolvedCallImpl<FunctionDescriptor>> extensionFunctionDescriptors = ResolvedCallImpl.convertCollection(scope.getFunctions(name));
@@ -966,7 +980,8 @@ public class CallResolver {
}
}
private boolean lookupExactSignature(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, List<JetType> parameterTypes, List<ResolvedCallImpl<FunctionDescriptor>> result) {
private static boolean lookupExactSignature(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, List<JetType> parameterTypes,
List<ResolvedCallImpl<FunctionDescriptor>> result) {
boolean found = false;
for (ResolvedCallImpl<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
@@ -979,7 +994,8 @@ public class CallResolver {
return found;
}
private boolean findExtensionFunctions(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, ReceiverDescriptor receiver, List<JetType> parameterTypes, List<ResolvedCallImpl<FunctionDescriptor>> result) {
private boolean findExtensionFunctions(Collection<ResolvedCallImpl<FunctionDescriptor>> candidates, ReceiverDescriptor receiver,
List<JetType> parameterTypes, List<ResolvedCallImpl<FunctionDescriptor>> result) {
boolean found = false;
for (ResolvedCallImpl<FunctionDescriptor> resolvedCall : candidates) {
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
@@ -994,7 +1010,7 @@ public class CallResolver {
return found;
}
private boolean checkValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull List<JetType> parameterTypes) {
private static boolean checkValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull List<JetType> parameterTypes) {
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
if (valueParameters.size() != parameterTypes.size()) return false;
for (int i = 0; i < valueParameters.size(); i++) {
@@ -84,8 +84,8 @@ public class DelegatingCall implements Call {
return delegate.getTypeArgumentList();
}
@NotNull
@Override
@Nullable
public PsiElement getCallElement() {
return delegate.getCallElement();
}
@@ -168,7 +168,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
candidateCall.recordValueArgument(valueParameter, new VarargValueArgument());
}
else {
// tracing.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
// tracing.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
tracing.noValueForParameter(temporaryTrace, valueParameter);
error = true;
}
@@ -22,6 +22,8 @@ import org.jetbrains.jet.lang.types.JetType;
import java.text.MessageFormat;
/**
* A specific type for subtype constraint of types.
*
* @author abreslav
*/
public enum ConstraintType implements Comparable<ConstraintType> {
@@ -33,7 +35,7 @@ public enum ConstraintType implements Comparable<ConstraintType> {
EXPECTED_TYPE("Resulting type is {0} but {1} was expected"),
PARAMETER_BOUND("Type parameter bound is not satisfied: {0} is not a subtype of {1}");
private final String errorMessageTemplate; // {0} is subtype, {1} is supertye
private final String errorMessageTemplate; // {0} is subtype, {1} is supertype
private ConstraintType(@NotNull String errorMessageTemplate) {
this.errorMessageTemplate = errorMessageTemplate;
@@ -35,7 +35,7 @@ public final class JetScopeUtils {
/**
* Get receivers in order of locality, so that the closest (the most local) receiver goes first
* A wrapper for {@link JetScope#getImplicitReceiversHierarchy(java.util.List)}
* A wrapper for {@link JetScope#getImplicitReceiversHierarchy(List)}
*
* @param scope Scope for getting receivers hierarchy.
* @return receivers hierarchy.
@@ -347,7 +347,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
return null;
}
private static OverloadResolutionResults<FunctionDescriptor> resolveFakeCall(ExpressionReceiver receiver, ExpressionTypingContext context, String name) {
public static OverloadResolutionResults<FunctionDescriptor> resolveFakeCall(ExpressionReceiver receiver,
ExpressionTypingContext context, String name) {
JetReferenceExpression fake = JetPsiFactory.createSimpleName(context.getProject(), "fake");
BindingTrace fakeTrace = new BindingTraceContext();
Call call = CallMaker.makeCall(fake, receiver, null, fake, Collections.<ValueArgument>emptyList());
@@ -42,6 +42,9 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
* @author abreslav
*/
public class DataFlowUtils {
private DataFlowUtils() {
}
@NotNull
public static DataFlowInfo extractDataFlowInfoFromCondition(@Nullable JetExpression condition, final boolean conditionValue, @Nullable final WritableScope scopeToExtend, final ExpressionTypingContext context) {
if (condition == null) return context.dataFlowInfo;
@@ -25,24 +25,22 @@ import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetPattern;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.*;
import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.Variance;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -53,7 +51,10 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
* @author abreslav
*/
public class ExpressionTypingUtils {
private ExpressionTypingUtils() {
}
@Nullable
protected static ExpressionReceiver getExpressionReceiver(@NotNull JetExpression expression, @Nullable JetType type) {
if (type == null) return null;
@@ -165,4 +166,84 @@ public class ExpressionTypingUtils {
);
return ControlStructureTypingVisitor.checkIterableConvention(expressionReceiver, context) != null;
}
/**
* Check that function or property with the given qualified name can be resolved in given scope and called on given receiver
*
* @param callableFQN
* @param project
* @param scope
* @return
*/
public static List<CallableDescriptor> canFindSuitableCall(
@NotNull String callableFQN,
@NotNull Project project,
@NotNull JetExpression receiverExpression,
@NotNull JetType receiverType,
@NotNull JetScope scope) {
WritableScopeWithImports writableScopeWithImports = new WritableScopeImpl(
scope, scope.getContainingDeclaration(), RedeclarationHandler.DO_NOTHING);
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, callableFQN);
ImportsResolver.ImportResolver importResolver = new ImportsResolver.ImportResolver(new BindingTraceContext(), false);
Collection<? extends DeclarationDescriptor> declarationDescriptors = importResolver.processImportReference(
importDirective, scope,
new Importer.StandardImporter(writableScopeWithImports, false));
List<CallableDescriptor> callableExtensionDescriptors = new ArrayList<CallableDescriptor>();
ReceiverDescriptor receiverDescriptor = new ExpressionReceiver(receiverExpression, receiverType);
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof CallableDescriptor) {
CallableDescriptor callableDescriptor = (CallableDescriptor) declarationDescriptor;
if (checkIsExtensionCallable(receiverDescriptor, callableDescriptor)) {
callableExtensionDescriptors.add(callableDescriptor);
}
}
}
return callableExtensionDescriptors;
}
/*
* Checks if receiver declaration could be resolved to call expected receiver.
*/
public static boolean checkIsExtensionCallable (
@NotNull ReceiverDescriptor expectedReceiver,
@NotNull CallableDescriptor receiverArgument
) {
JetType type = expectedReceiver.getType();
if (checkReceiverResolution(expectedReceiver, type, receiverArgument)) return true;
if (type.isNullable()) {
JetType notNullableType = TypeUtils.makeNotNullable(type);
if (checkReceiverResolution(expectedReceiver, notNullableType, receiverArgument)) return true;
}
return false;
}
private static boolean checkReceiverResolution (
@NotNull ReceiverDescriptor expectedReceiver,
@NotNull JetType receiverType,
@NotNull CallableDescriptor receiverArgument
) {
ConstraintSystem constraintSystem = new ConstraintSystemImpl(ConstraintResolutionListener.DO_NOTHING);
for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) {
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT);
}
ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter();
if (expectedReceiver.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(ConstraintType.RECEIVER.assertSubtyping(receiverType, receiverParameter.getType()));
}
else if (expectedReceiver.exists() || receiverParameter.exists()) {
// Only one of receivers exist
return false;
}
ConstraintSystemSolution solution = constraintSystem.solve();
return solution.getStatus().isSuccessful();
}
}
@@ -209,4 +209,13 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
public Icon getElementIcon(final int flags) {
return PsiClassImplUtil.getClassIcon(flags, this);
}
@Override
public String toString() {
try {
return JetLightClass.class.getSimpleName() + ":" + getQualifiedName();
} catch (Throwable e) {
return JetLightClass.class.getSimpleName() + ":" + e.toString();
}
}
}
+1
View File
@@ -13,6 +13,7 @@
<orderEntry type="module" module-name="stdlib" />
<orderEntry type="module" module-name="cli" />
<orderEntry type="library" name="idea-full" level="project" />
<orderEntry type="library" name="asm" level="project" />
</component>
</module>
@@ -99,7 +99,7 @@ public class ForTestCompileStdlib {
private static void compileKotlinPartOfStdlib(File destdir) throws IOException {
// lame
KotlinCompiler.exec("-output", destdir.getPath(), "-src", "./stdlib/ktSrc", "-stdlib", destdir.getAbsolutePath());
KotlinCompiler.exec(System.err, "-output", destdir.getPath(), "-src", "./stdlib/ktSrc", "-stdlib", destdir.getAbsolutePath());
}
private static List<File> javaFilesInDir(File dir) {
@@ -22,6 +22,7 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jetbrains.jet.compiler.CompileSession;
import org.jetbrains.jet.compiler.MessageRenderer;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetDeclaration;
@@ -84,7 +85,7 @@ public class TestlibTest extends CodegenTestCase {
session.addSources(localFileSystem.findFileByPath(JetParsingTest.getTestDataDir() + "/../../testlib/test"));
session.addSources(localFileSystem.findFileByPath(JetParsingTest.getTestDataDir() + "/../../kunit/src"));
if (!session.analyze(System.err)) {
if (!session.analyze(System.err, MessageRenderer.PLAIN)) {
throw new RuntimeException("There were compilation errors");
}
@@ -1,72 +0,0 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.caches;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.xml.impl.schema.TypeDescriptor;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import java.util.ArrayList;
import java.util.Collection;
/**
* Get jet declarations from java that could be used in completion. Unlike the real jet resolver this helper is allowed
* to return partially unresolved descriptors in exchange of execution speed.
*
* @author Nikolay Krasko
*/
class JetFromJavaDescriptorHelper {
private JetFromJavaDescriptorHelper() {
}
/**
* Get java equivalents for jet top level classes.
*/
static PsiClass[] getClassesForJetNamespaces(Project project, GlobalSearchScope scope) {
return PsiShortNamesCache.getInstance(project).getClassesByName(JvmAbi.PACKAGE_CLASS, scope);
}
/**
* Get names that could have jet descriptor equivalents. It could be inaccurate and return more results than necessary.
*/
static Collection<String> getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) {
final ArrayList<String> result = new ArrayList<String>();
for (PsiClass jetNamespaceClass : getClassesForJetNamespaces(project, scope)) {
for (PsiMethod psiMethod : jetNamespaceClass.getMethods()) {
if (psiMethod.getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
result.add(psiMethod.getName());
}
}
}
return result;
}
static Collection<String> getTopExtensionFunctionNames(TypeDescriptor typeDescriptor, Project project,
GlobalSearchScope scope) {
return getPossiblePackageDeclarationsNames(project, scope);
}
}
@@ -0,0 +1,134 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.caches;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
import com.intellij.psi.impl.java.stubs.index.JavaMethodNameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.PsiTreeUtil;
import jet.runtime.typeinfo.JetValueParameter;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.kt.JetValueParameterAnnotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Get jet declarations from java that could be used in completion. Unlike the real jet resolver this helper is allowed
* to return partially unresolved descriptors in exchange of execution speed.
*
* @author Nikolay Krasko
*/
class JetFromJavaDescriptorHelper {
private JetFromJavaDescriptorHelper() {
}
/**
* Get java equivalents for jet top level classes.
*/
static PsiClass[] getClassesForJetNamespaces(Project project, GlobalSearchScope scope) {
return PsiShortNamesCache.getInstance(project).getClassesByName(JvmAbi.PACKAGE_CLASS, scope);
}
/**
* Get names that could have jet descriptor equivalents. It could be inaccurate and return more results than necessary.
*/
static Collection<String> getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) {
Collection<String> result = new ArrayList<String>();
for (PsiClass jetNamespaceClass : getClassesForJetNamespaces(project, scope)) {
for (PsiMethod psiMethod : jetNamespaceClass.getMethods()) {
if (psiMethod.getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
result.add(psiMethod.getName());
}
}
}
return result;
}
static Collection<String> getTopExtensionFunctionNames(Project project, GlobalSearchScope scope) {
// Extension function should have an parameter of type JetValueParameter with explicit receiver parameter.
Set<String> extensionNames = new HashSet<String>();
Collection<PsiAnnotation> valueParametersAnnotations = JavaAnnotationIndex.getInstance().get(
JetValueParameter.class.getSimpleName(), project, scope);
for (PsiAnnotation parameterAnnotation : valueParametersAnnotations) {
String qualifiedName = parameterAnnotation.getQualifiedName();
if (qualifiedName == null || !qualifiedName.equals(JetValueParameter.class.getCanonicalName())) {
continue;
}
if (!new JetValueParameterAnnotation(parameterAnnotation).receiver()) {
continue;
}
PsiMethod psiMethod = PsiTreeUtil.getParentOfType(parameterAnnotation, PsiMethod.class);
if (psiMethod != null) {
extensionNames.add(psiMethod.getName());
}
}
return extensionNames;
}
static Collection<PsiMethod> getTopExtensionFunctionByName(String name, Project project, GlobalSearchScope scope) {
Set<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
Collection<PsiMethod> psiMethods = JavaMethodNameIndex.getInstance().get(name, project, scope);
for (PsiMethod psiMethod : psiMethods) {
if (psiMethod == null) {
continue;
}
// Check this is top level function
PsiClass containingClass = psiMethod.getContainingClass();
if (containingClass == null || !JvmAbi.PACKAGE_CLASS.equals(containingClass.getName())) {
continue;
}
// Should be parameter with JetValueParameter.receiver == true
for (PsiParameter parameter : psiMethod.getParameterList().getParameters()) {
PsiModifierList modifierList = parameter.getModifierList();
if (modifierList != null) {
for (PsiAnnotation psiAnnotation : modifierList.getAnnotations()) {
if (!JetValueParameter.class.getCanonicalName().equals(psiAnnotation.getQualifiedName())) {
continue;
}
if (new JetValueParameterAnnotation(psiAnnotation).receiver()) {
selectedMethods.add(psiMethod);
}
}
}
}
}
return selectedMethods;
}
}
@@ -20,20 +20,20 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.asJava.JavaElementFinder;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.stubindex.JetExtensionFunctionNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex;
@@ -68,8 +68,8 @@ public class JetShortNamesCache extends PsiShortNamesCache {
@NotNull
@Override
public String[] getAllClassNames() {
final Collection<String> classNames = JetShortClassNameIndex.getInstance().getAllKeys(project);
return classNames.toArray(new String[classNames.size()]);
Collection<String> classNames = JetShortClassNameIndex.getInstance().getAllKeys(project);
return ArrayUtil.toStringArray(classNames);
}
/**
@@ -77,10 +77,10 @@ public class JetShortNamesCache extends PsiShortNamesCache {
*/
@NotNull
@Override
public PsiClass[] getClassesByName(@NotNull @NonNls final String name, @NotNull GlobalSearchScope scope) {
public PsiClass[] getClassesByName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope) {
// Quick check for classes from getAllClassNames()
final Collection<String> classNames = JetShortClassNameIndex.getInstance().getAllKeys(project);
Collection<String> classNames = JetShortClassNameIndex.getInstance().getAllKeys(project);
if (!classNames.contains(name)) {
return new PsiClass[0];
}
@@ -89,7 +89,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) {
if (QualifiedNamesUtil.fqnToShortName(fqName).equals(name)) {
final PsiClass psiClass = javaElementFinder.findClass(fqName, scope);
PsiClass psiClass = javaElementFinder.findClass(fqName, scope);
if (psiClass != null) {
result.add(psiClass);
}
@@ -104,14 +104,14 @@ public class JetShortNamesCache extends PsiShortNamesCache {
// TODO: Implement it. Is it called somewhere?
}
public Collection<String> getALlJetClassFQNames() {
final BindingContext context = getResolutionContext(GlobalSearchScope.allScope(project));
return context.getKeys(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR);
}
// public Collection<String> getALlJetClassFQNames() {
// final BindingContext context = getResolutionContext(GlobalSearchScope.allScope(project));
// return context.getKeys(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR);
// }
@NotNull
public Collection<String> getFQNamesByName(@NotNull final String name, @NotNull GlobalSearchScope scope) {
final BindingContext context = getResolutionContext(scope);
BindingContext context = getResolutionContext(scope);
return Collections2.filter(context.getKeys(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR), new Predicate<String>() {
@Override
public boolean apply(@Nullable String fqName) {
@@ -128,26 +128,24 @@ public class JetShortNamesCache extends PsiShortNamesCache {
*/
@NotNull
public Collection<String> getAllTopLevelFunctionNames() {
final HashSet<String> functionNames = new HashSet<String>();
Set<String> functionNames = new HashSet<String>();
functionNames.addAll(JetShortFunctionNameIndex.getInstance().getAllKeys(project));
functionNames.addAll(JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, GlobalSearchScope.allScope(project)));
return functionNames;
}
@NotNull
public Collection<SimpleFunctionDescriptor> getTopLevelFunctionDescriptorsByName(final @NotNull String name,
final @NotNull GlobalSearchScope scope) {
public Collection<SimpleFunctionDescriptor> getTopLevelFunctionDescriptorsByName(@NotNull String name,
@NotNull GlobalSearchScope scope) {
// TODO: Add jet function in jar-dependencies (those functions are missing in BindingContext and stubs)
final Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
final BindingContext context = getResolutionContext(scope);
BindingContext context = getResolutionContext(scope);
final HashSet<SimpleFunctionDescriptor> result = new HashSet<SimpleFunctionDescriptor>();
HashSet<SimpleFunctionDescriptor> result = new HashSet<SimpleFunctionDescriptor>();
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
final SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
if (functionDescriptor != null) {
result.add(functionDescriptor);
}
@@ -157,11 +155,11 @@ public class JetShortNamesCache extends PsiShortNamesCache {
}
@NotNull
public BindingContext getResolutionContext(final @NotNull GlobalSearchScope scope) {
public BindingContext getResolutionContext(@NotNull GlobalSearchScope scope) {
return WholeProjectAnalyzerFacade.analyzeProjectWithCache(project, scope);
}
public Collection<JetNamedFunction> getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) {
public Collection<JetNamedFunction> getTopLevelFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
return JetShortFunctionNameIndex.getInstance().get(name, project, scope);
}
@@ -173,35 +171,28 @@ public class JetShortNamesCache extends PsiShortNamesCache {
*/
@NotNull
public Collection<String> getAllJetExtensionFunctionsNames(@NotNull GlobalSearchScope scope) {
final Set<String> extensionFunctionNames = new HashSet<String>();
Set<String> extensionFunctionNames = new HashSet<String>();
extensionFunctionNames.addAll(JetExtensionFunctionNameIndex.getInstance().getAllKeys(project));
extensionFunctionNames.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(null, project, scope));
extensionFunctionNames.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(project, scope));
return extensionFunctionNames;
}
public Collection<SimpleFunctionDescriptor> getAllJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
// TODO: Add jet extension functions in jar-dependencies (those functions are missing in BindingContext and stubs)
public Collection<PsiElement> getJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
HashSet<PsiElement> functions = new HashSet<PsiElement>();
functions.addAll(JetExtensionFunctionNameIndex.getInstance().get(name, project, scope));
functions.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionByName(name, project, scope));
final Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
return functions;
}
final BindingContext context = getResolutionContext(scope);
public Collection<JetNamedFunction> getJetFunctionsByName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope) {
return JetShortFunctionNameIndex.getInstance().get(name, project, scope);
}
final HashSet<SimpleFunctionDescriptor> result = new HashSet<SimpleFunctionDescriptor>();
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
final SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
if (functionDescriptor != null) {
if (functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
if (functionDescriptor.getExpectedThisObject() != ReceiverDescriptor.NO_RECEIVER) {
result.add(functionDescriptor);
}
}
}
}
return result;
public Collection<String> getAllJetFunctionsNames() {
return JetShortFunctionNameIndex.getInstance().getAllKeys(project);
}
@NotNull
@@ -219,11 +210,12 @@ public class JetShortNamesCache extends PsiShortNamesCache {
@NotNull
@Override
public String[] getAllMethodNames() {
return new String[0];
return ArrayUtil.EMPTY_STRING_ARRAY;
}
@Override
public void getAllMethodNames(@NotNull HashSet<String> set) {
set.addAll(JetShortFunctionNameIndex.getInstance().getAllKeys(project));
}
@NotNull
@@ -235,7 +227,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
@NotNull
@Override
public String[] getAllFieldNames() {
return new String[0];
return ArrayUtil.EMPTY_STRING_ARRAY;
}
@Override
@@ -37,6 +37,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Chunk;
import com.intellij.util.SystemProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.plugin.JetFileType;
import java.io.*;
@@ -199,10 +201,10 @@ public class JetCompiler implements TranslatingCompiler {
try {
String line = reader.readLine();
if (line == null) break;
listener.onTextAvailable(new ProcessEvent(NullProcessHandler.INSTANCE, line), ProcessOutputTypes.STDOUT);
listener.onTextAvailable(new ProcessEvent(NullProcessHandler.INSTANCE, line + "\n"), ProcessOutputTypes.STDERR);
} catch (IOException e) {
// Can't be
throw new RuntimeException(e);
throw new IllegalStateException(e);
}
}
@@ -218,7 +220,7 @@ public class JetCompiler implements TranslatingCompiler {
Class<?> kompiler = Class.forName(compilerClassName, true, loader);
Method exec = kompiler.getDeclaredMethod("exec", PrintStream.class, String[].class);
String[] arguments = { "-module", scriptFile.getAbsolutePath(), "-output", path(outputDir) };
String[] arguments = { "-module", scriptFile.getAbsolutePath(), "-output", path(outputDir), "-tags" };
context.addMessage(INFORMATION, "Using kotlinHome=" + kotlinHome, "", -1, -1);
context.addMessage(INFORMATION, "Invoking in-process compiler " + compilerClassName + " with arguments " + Arrays.asList(arguments), "", -1, -1);
@@ -228,7 +230,7 @@ public class JetCompiler implements TranslatingCompiler {
return ((Integer) rc).intValue();
}
else {
throw new RuntimeException("Unexpected return: " + rc);
throw new IllegalStateException("Unexpected return: " + rc);
}
} catch (Throwable e) {
LOG.error(e);
@@ -267,6 +269,7 @@ public class JetCompiler implements TranslatingCompiler {
params.setMainClass("org.jetbrains.jet.cli.KotlinCompiler");
params.getProgramParametersList().add("-module", scriptFile.getAbsolutePath());
params.getProgramParametersList().add("-output", path(outputDir));
params.getProgramParametersList().add("-tags");
for (File jar : kompilerClasspath(kotlinHome, compileContext)) {
params.getClassPath().add(jar);
@@ -302,77 +305,7 @@ public class JetCompiler implements TranslatingCompiler {
}
private static ProcessAdapter createProcessListener(final CompileContext compileContext) {
return new ProcessAdapter() {
StringBuilder stderr = null;
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
String text = event.getText();
String levelCode = parsePrefix(text);
if (outputType == ProcessOutputTypes.STDERR) {
if (stderr == null) {
stderr = new StringBuilder();
}
stderr.append(text);
return;
}
if (levelCode != null) {
CompilerMessageCategory category = categories.get(levelCode);
text = text.substring(levelCode.length());
String path = "";
int line = -1;
int column = -1;
int colonIndex = text.indexOf(':');
if (text.startsWith(":")) {
text = text.substring(1);
} else if (colonIndex > 0) {
path = "file://" + text.substring(0, colonIndex).trim();
text = text.substring(colonIndex + 1);
Pattern position = Pattern.compile("\\((\\d+),\\s*(\\d+)\\)");
Matcher matcher = position.matcher(text);
if (matcher.find()) {
line = Integer.parseInt(matcher.group(1));
column = Integer.parseInt(matcher.group(2));
text = text.substring(matcher.group(0).length());
}
}
compileContext.addMessage(category, text, path, line, column);
}
else {
compileContext.addMessage(INFORMATION, text, "", -1, -1);
}
}
@Override
public void processTerminated(ProcessEvent event) {
if (event.getExitCode() != 0) {
compileContext.addMessage(ERROR, "Compiler terminated with exit code: " + event.getExitCode(), "", -1, -1);
}
// By alex.tkachman:
if (stderr != null) {
compileContext.addMessage(ERROR, "stderr output:\r\n" + stderr.toString(), "", -1, -1);
}
}
};
}
private static String[] messagePrefixes = new String[] {"ERROR:", "WARNING:", "INFO:"} ;
private static Map<String, CompilerMessageCategory> categories = new HashMap<String, CompilerMessageCategory>();
static {
categories.put("ERROR:", ERROR);
categories.put("WARNING:", WARNING);
categories.put("INFORMATION:", INFORMATION);
}
private static String parsePrefix(String message) {
for (String prefix : messagePrefixes) {
if (message.startsWith(prefix)) return prefix;
}
return null;
return new CompilerProcessListener(compileContext);
}
private static String path(VirtualFile root) {
@@ -406,4 +339,167 @@ public class JetCompiler implements TranslatingCompiler {
throw new UnsupportedOperationException("getProcessInput is not implemented");
}
}
private static class CompilerProcessListener extends ProcessAdapter {
private static final Pattern DIAGNOSTIC_PATTERN = Pattern.compile("<(ERROR|WARNING|INFO|EXCEPTION)", Pattern.MULTILINE);
private static final Pattern OPEN_TAG_END_PATTERN = Pattern.compile(">", Pattern.MULTILINE | Pattern.DOTALL);
private static final Pattern ATTRIBUTE_PATTERN = Pattern.compile("\\s*(path|line|column)\\s*=\\s*\"(.*?)\"", Pattern.MULTILINE | Pattern.DOTALL);
private static final Pattern MESSAGE_PATTERN = Pattern.compile("(.*?)</(ERROR|WARNING|INFO|EXCEPTION)>", Pattern.MULTILINE | Pattern.DOTALL);
private enum State {
WAITING, ATTRIBUTES, MESSAGE
}
private static class CompilerMessage {
private CompilerMessageCategory messageCategory;
private boolean isException;
private @Nullable String url;
private @Nullable Integer line;
private @Nullable Integer column;
private String message;
public void setMessageCategoryFromString(String tagName) {
boolean exception = "EXCEPTION".equals(tagName);
if (Severity.ERROR.toString().equals(tagName) || exception) {
messageCategory = ERROR;
isException = exception;
}
else if (Severity.WARNING.toString().equals(tagName)) {
messageCategory = WARNING;
}
else {
messageCategory = INFORMATION;
}
}
public void setAttributeFromStrings(String name, String value) {
if ("path".equals(name)) {
url = "file://" + value.trim();
}
else if ("line".equals(name)) {
line = safeParseInt(value);
}
else if ("column".equals(name)) {
column = safeParseInt(value);
}
}
@Nullable
private static Integer safeParseInt(String value) {
try {
return Integer.parseInt(value.trim());
}
catch (NumberFormatException e) {
return null;
}
}
public void setMessage(String message) {
this.message = message;
}
public void reportTo(CompileContext compileContext) {
compileContext.addMessage(messageCategory, message, url == null ? "" : url, line == null ? -1 : line, column == null ? -1 : column);
if (isException) {
LOG.error(message);
}
}
}
private final CompileContext compileContext;
private final StringBuilder output = new StringBuilder();
private int firstUnprocessedIndex = 0;
private State state = State.WAITING;
private CompilerMessage currentCompilerMessage;
public CompilerProcessListener(CompileContext compileContext) {
this.compileContext = compileContext;
}
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
String text = event.getText();
if (outputType == ProcessOutputTypes.STDERR) {
output.append(text);
// We loop until the state stabilizes
State lastState;
do {
lastState = state;
switch (state) {
case WAITING: {
Matcher matcher = matcher(DIAGNOSTIC_PATTERN);
if (find(matcher)) {
currentCompilerMessage = new CompilerMessage();
currentCompilerMessage.setMessageCategoryFromString(matcher.group(1));
state = State.ATTRIBUTES;
}
break;
}
case ATTRIBUTES: {
Matcher matcher = matcher(ATTRIBUTE_PATTERN);
int indexDelta = 0;
while (matcher.find()) {
handleSkippedOutput(output.subSequence(firstUnprocessedIndex + indexDelta, firstUnprocessedIndex + matcher.start()));
currentCompilerMessage.setAttributeFromStrings(matcher.group(1), matcher.group(2));
indexDelta = matcher.end();
}
firstUnprocessedIndex += indexDelta;
Matcher endMatcher = matcher(OPEN_TAG_END_PATTERN);
if (find(endMatcher)) {
state = State.MESSAGE;
}
break;
}
case MESSAGE: {
Matcher matcher = matcher(MESSAGE_PATTERN);
if (find(matcher)) {
currentCompilerMessage.setMessage(matcher.group(1));
currentCompilerMessage.reportTo(compileContext);
state = State.WAITING;
}
break;
}
}
}
while (state != lastState);
}
else {
compileContext.addMessage(INFORMATION, text, "", -1, -1);
}
}
private boolean find(Matcher matcher) {
boolean result = matcher.find();
if (result) {
handleSkippedOutput(output.subSequence(firstUnprocessedIndex, firstUnprocessedIndex + matcher.start()));
firstUnprocessedIndex += matcher.end();
}
return result;
}
private Matcher matcher(Pattern pattern) {
return pattern.matcher(output.subSequence(firstUnprocessedIndex, output.length()));
}
@Override
public void processTerminated(ProcessEvent event) {
if (firstUnprocessedIndex < output.length()) {
handleSkippedOutput(output.substring(firstUnprocessedIndex).trim());
}
if (event.getExitCode() != 0) {
compileContext.addMessage(ERROR, "Compiler terminated with exit code: " + event.getExitCode(), "", -1, -1);
}
}
private void handleSkippedOutput(CharSequence substring) {
String message = substring.toString();
if (!message.trim().isEmpty()) {
compileContext.addMessage(ERROR, message, "", -1, -1);
}
}
}
}
@@ -21,7 +21,9 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReference;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
@@ -29,19 +31,23 @@ import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.psi.JetUserType;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.caches.JetCacheManager;
import org.jetbrains.jet.plugin.caches.JetShortNamesCache;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.references.JetSimpleNameReference;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* @author Nikolay Krasko
@@ -52,20 +58,20 @@ public class JetCompletionContributor extends CompletionContributor {
new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context,
final @NotNull CompletionResultSet result) {
@NotNull CompletionResultSet result) {
final HashSet<LookupPositionObject> positions = new HashSet<LookupPositionObject>();
Set<LookupPositionObject> positions = new HashSet<LookupPositionObject>();
if (result.getPrefixMatcher().getPrefix().isEmpty()) {
return;
}
final PsiElement position = parameters.getPosition();
PsiElement position = parameters.getPosition();
if (!(position.getContainingFile() instanceof JetFile)) {
return;
}
final JetSimpleNameReference jetReference = getJetReference(parameters);
JetSimpleNameReference jetReference = getJetReference(parameters);
if (jetReference != null) {
for (Object variant : jetReference.getVariants()) {
addReferenceVariant(result, variant, positions);
@@ -74,6 +80,7 @@ public class JetCompletionContributor extends CompletionContributor {
if (shouldRunTopLevelCompletion(parameters)) {
addClasses(parameters, result, positions);
addJetTopLevelFunctions(result, position, positions);
addJetExtensionFunctions(jetReference.getExpression(), result, position);
}
result.stopHere();
@@ -82,10 +89,66 @@ public class JetCompletionContributor extends CompletionContributor {
});
}
// TODO: Make it work for properties
private static void addJetExtensionFunctions(JetSimpleNameExpression expression, CompletionResultSet result, PsiElement position) {
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) position.getContainingFile());
JetExpression receiverExpression = expression.getReceiverExpression();
if (receiverExpression != null) {
JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
JetScope scope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression);
if (expressionType != null && scope != null) {
JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
Collection<String> extensionFunctionsNames = namesCache.getAllJetExtensionFunctionsNames(
GlobalSearchScope.allScope(position.getProject()));
Set<String> functionFQNs = new HashSet<String>();
// Collect all possible extension function qualified names
for (String name : extensionFunctionsNames) {
if (result.getPrefixMatcher().prefixMatches(name)) {
Collection<PsiElement> extensionFunctions =
namesCache.getJetExtensionFunctionsByName(name, GlobalSearchScope.allScope(position.getProject()));
for (PsiElement extensionFunction : extensionFunctions) {
if (extensionFunction instanceof JetNamedFunction) {
functionFQNs.add(JetPsiUtil.getFQName((JetNamedFunction) extensionFunction));
}
else if (extensionFunction instanceof PsiMethod) {
PsiMethod function = (PsiMethod) extensionFunction;
PsiClass containingClass = function.getContainingClass();
if (containingClass != null) {
String classFQN = containingClass.getQualifiedName();
if (classFQN != null) {
String classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN);
functionFQNs.add(QualifiedNamesUtil.combine(classParentFQN, function.getName()));
}
}
}
}
}
}
// Iterate through the function with attempt to resolve found functions
for (String functionFQN : functionFQNs) {
for (CallableDescriptor functionDescriptor : ExpressionTypingUtils.canFindSuitableCall(
functionFQN, position.getProject(), receiverExpression, expressionType, scope)) {
result.addElement(DescriptorLookupConverter.createLookupElement(context, functionDescriptor));
}
}
}
}
}
private static void addReferenceVariant(
@NotNull CompletionResultSet result,
@NotNull Object variant,
@NotNull final HashSet<LookupPositionObject> positions) {
@NotNull Set<LookupPositionObject> positions) {
if (variant instanceof LookupElement) {
addCompletionToResult(result, (LookupElement) variant, positions);
@@ -96,15 +159,15 @@ public class JetCompletionContributor extends CompletionContributor {
}
private static void addJetTopLevelFunctions(@NotNull CompletionResultSet result, @NotNull PsiElement position,
@NotNull final HashSet<LookupPositionObject> positions) {
@NotNull Set<LookupPositionObject> positions) {
String actualPrefix = result.getPrefixMatcher().getPrefix();
final Project project = position.getProject();
Project project = position.getProject();
final JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
final Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
BindingContext resolutionContext = namesCache.getResolutionContext(scope);
@@ -121,9 +184,9 @@ public class JetCompletionContributor extends CompletionContributor {
* Jet classes will be added as java completions for unification
*/
private static void addClasses(
@NotNull final CompletionParameters parameters,
@NotNull CompletionParameters parameters,
@NotNull final CompletionResultSet result,
@NotNull final HashSet<LookupPositionObject> positions) {
@NotNull final Set<LookupPositionObject> positions) {
JetClassCompletionContributor.addClasses(parameters, result, new Consumer<LookupElement>() {
@Override
@@ -134,7 +197,7 @@ public class JetCompletionContributor extends CompletionContributor {
}
private static boolean shouldRunTopLevelCompletion(@NotNull CompletionParameters parameters) {
final PsiElement element = parameters.getPosition();
PsiElement element = parameters.getPosition();
if (parameters.getInvocationCount() > 1) {
return true;
@@ -158,9 +221,9 @@ public class JetCompletionContributor extends CompletionContributor {
@Nullable
private static JetSimpleNameReference getJetReference(@NotNull CompletionParameters parameters) {
final PsiElement element = parameters.getPosition();
PsiElement element = parameters.getPosition();
if (element.getParent() != null) {
final PsiElement parent = element.getParent();
PsiElement parent = element.getParent();
PsiReference[] references = parent.getReferences();
if (references.length != 0) {
@@ -176,11 +239,11 @@ public class JetCompletionContributor extends CompletionContributor {
}
private static void addCompletionToResult(
@NotNull final CompletionResultSet result,
@NotNull CompletionResultSet result,
@NotNull LookupElement element,
@NotNull HashSet<LookupPositionObject> positions) {
@NotNull Set<LookupPositionObject> positions) {
final LookupPositionObject lookupPosition = getLookupPosition(element);
LookupPositionObject lookupPosition = getLookupPosition(element);
if (lookupPosition != null) {
if (!positions.contains(lookupPosition)) {
positions.add(lookupPosition);
@@ -195,14 +258,14 @@ public class JetCompletionContributor extends CompletionContributor {
}
private static LookupPositionObject getLookupPosition(LookupElement element) {
final Object lookupObject = element.getObject();
Object lookupObject = element.getObject();
if (lookupObject instanceof PsiElement) {
// PsiElement psiElement = (PsiElement) lookupObject;
return new LookupPositionObject((PsiElement) lookupObject);
}
else if (lookupObject instanceof JetLookupObject) {
// JetLookupObject jetLookupObject = (JetLookupObject) lookupObject;
final PsiElement psiElement = ((JetLookupObject) lookupObject).getPsiElement();
PsiElement psiElement = ((JetLookupObject) lookupObject).getPsiElement();
if (psiElement != null) {
return new LookupPositionObject(psiElement);
}
@@ -210,4 +273,9 @@ public class JetCompletionContributor extends CompletionContributor {
return null;
}
@Override
public void beforeCompletion(@NotNull CompletionInitializationContext context) {
super.beforeCompletion(context); //To change body of overridden methods use File | Settings | File Templates.
}
}
@@ -29,6 +29,9 @@ import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
import org.jetbrains.jet.plugin.references.JetPackageReference;
/**
* Performs completion in package directive. Should suggest only packages and avoid showing fake package produced by
* DUMMY_IDENTIFIER.
*
* @author Nikolay Krasko
*/
public class JetPackagesContributor extends CompletionContributor {
@@ -115,11 +115,6 @@ public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
return;
}
// No auto import for qualified expressions
if (PsiTreeUtil.getParentOfType(element, JetQualifiedExpression.class) != null) {
return;
}
if (context.getFile() instanceof JetFile && item.getObject() instanceof JetLookupObject) {
final DeclarationDescriptor descriptor = ((JetLookupObject) item.getObject()).getDescriptor();
if (descriptor instanceof SimpleFunctionDescriptor) {
@@ -128,6 +123,13 @@ public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
SimpleFunctionDescriptor functionDescriptor = (SimpleFunctionDescriptor) descriptor;
final String fqn = DescriptorUtils.getFQName(functionDescriptor);
// Don't insert import for qualified expression if don't try to insert extension function
if (PsiTreeUtil.getParentOfType(element, JetQualifiedExpression.class) != null &&
!functionDescriptor.getReceiverParameter().exists()) {
return;
}
if (DescriptorUtils.isTopLevelFunction(functionDescriptor)) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -46,6 +46,9 @@ public class JetLiveTemplateCompletionContributor extends CompletionContributor
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull final CompletionResultSet result) {
if (parameters.getInvocationCount() == 0) {
return;
}
final PsiFile file = parameters.getPosition().getContainingFile();
final int offset = parameters.getOffset();
final List<TemplateImpl> templates = listApplicableTemplates(file, offset);
@@ -30,7 +30,7 @@ import org.jetbrains.jet.plugin.JetBundle;
public class JetSuggestVariableNameMacro extends Macro {
@Override
public String getName() {
return "suggestVariableName";
return "kotlinSuggestVariableName";
}
@Override
@@ -43,14 +43,16 @@ public class StubIndexServiceImpl implements StubIndexService {
public void indexFunction(PsiJetFunctionStub stub, IndexSink sink) {
String name = stub.getName();
if (name != null) {
if (!stub.isExtension()) {
if (stub.isTopLevel()) {
if (stub.isTopLevel()) {
// Collection only top level functions as only they are expected in completion without explicit import
if (!stub.isExtension()) {
sink.occurrence(JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY, name);
// sink.occurrence(JetIndexKeys.TOP_LEVEL_FUNCTION_FQNAME_KEY, name);
} else {
sink.occurrence(JetIndexKeys.EXTENSION_FUNCTION_SHORT_NAME_KEY, name);
// sink.occurrence(JetIndexKeys.EXTENSION_FUNCTION_FQNAME_KEY, name);
}
}
else {
sink.occurrence(JetIndexKeys.EXTENSION_FUNCTION_SHORT_NAME_KEY, name);
}
}
}
}
@@ -0,0 +1,13 @@
package first
import java.util.ArrayList
fun firstFun() {
val a = ArrayList<Int>()
a.toLinke<caret>
}
// RUNTIME: 1
// TIME: 2
// EXIST: toLinkedList
// NUMBER: 1
@@ -0,0 +1,15 @@
package first
trait TestedTrait() {
}
fun firstFun() {
val a = second.SomeTest<TestedTrait>()
a.testing<caret>
}
// EXIST: testingMethod
// EXIST: testingExpectedFunction
// ABSENT: testingUnexpectedFunction
// NUMBER: 2
@@ -0,0 +1,16 @@
package second
open class SomeOther() {}
class SomeTest<T> {
fun testingMethod() {
}
}
fun <U : SomeOther> SomeTest<U>.testingUnexpectedFunction() {
}
fun <W : Any> SomeTest<W>.testingExpectedFunction(i : Int) : String {
return ""
}
@@ -0,0 +1,11 @@
package first
fun firstFun() {
val a = SomeUnknownClass()
a.hello<caret>
}
// ABSENT: helloFun
// ABSENT: helloFunPreventAutoInsert
// ABSENT: helloWithParams
// NUMBER: 0
@@ -0,0 +1,11 @@
package second
fun String.helloFun() {
}
fun String.helloWithParams(i : Int) : String {
return ""
}
fun String.helloFunPreventAutoInsert() {
}
@@ -0,0 +1,12 @@
package first
fun firstFun() {
val a : String? = ""
a.hello<caret>
}
// EXIST: helloFun
// EXIST: helloFunPreventAutoInsert
// EXIST: helloWithParams
// ABSENT: helloFake
// NUMBER: 3
@@ -0,0 +1,14 @@
package second
fun String.helloFun() {
}
fun String.helloWithParams(i : Int) : String {
return ""
}
fun String.helloFunPreventAutoInsert() {
}
fun Int.helloFake() {
}
@@ -0,0 +1,12 @@
package first
import second.SomeTestClass
fun firstFun() {
SomeTestClass().some<caret>
}
// EXIST: someProperty
// EXIST: someOtherProperty
// EXIST: someSelfProperty
// NUMBER: 3
@@ -0,0 +1,8 @@
package second
class SomeTestClass() {
}
val SomeTestClass.someProperty = 12
var SomeTestClass.someOtherProperty = ""
val SomeTestClass.someSelfProperty = SomeTestClass()
@@ -0,0 +1,12 @@
package first
fun firstFun() {
val a = ""
a.hello<caret>
}
// EXIST: helloFun
// EXIST: helloFunPreventAutoInsert
// EXIST: helloWithParams
// ABSENT: helloFake
// NUMBER: 3
@@ -0,0 +1,14 @@
package second
fun String.helloFun() {
}
fun String.helloWithParams(i : Int) : String {
return ""
}
fun String.helloFunPreventAutoInsert() {
}
fun Int.helloFake() {
}
@@ -0,0 +1,6 @@
package first
fun firstFun() {
val a = ""
a.hello<caret>
}
@@ -0,0 +1,4 @@
package second
fun String.helloFun() {
}
@@ -0,0 +1,8 @@
package first
import second.helloFun
fun firstFun() {
val a = ""
a.helloFun()
}
@@ -68,17 +68,17 @@ public class ExpectedCompletionUtils {
@Nullable
public Integer getExpectedNumber(String fileText) {
final String[] numberStrings = findListWithPrefix(numberLinePrefix, fileText);
if (numberStrings.length > 0) {
return Integer.parseInt(numberStrings[0]);
}
return null;
return getPrefixedInt(fileText, numberLinePrefix);
}
@Nullable
public Integer getExecutionTime(String fileText) {
final String[] numberStrings = findListWithPrefix(executionTimePrefix, fileText);
return getPrefixedInt(fileText, executionTimePrefix);
}
@Nullable
public static Integer getPrefixedInt(String fileText, String prefix) {
final String[] numberStrings = findListWithPrefix(prefix, fileText);
if (numberStrings.length > 0) {
return Integer.parseInt(numberStrings[0]);
}
@@ -45,6 +45,10 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
doTest();
}
public void testExtensionFromStandardLibrary() {
doTest();
}
public void testFromImports() {
doTest();
}
@@ -101,6 +105,8 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
doTest();
}
@Override
protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/basic").getPath() +
@@ -22,7 +22,12 @@ import com.intellij.codeInsight.completion.LightCompletionTestCase;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import org.apache.commons.lang.SystemUtils;
import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
/**
@@ -47,32 +52,71 @@ public abstract class JetCompletionTestBase extends LightCompletionTestCase {
final String fileText = getFile().getText();
Integer completionTime = completionUtils.getExecutionTime(fileText);
complete(completionTime == null ? 1 : completionTime);
boolean withKotlinRuntime = ExpectedCompletionUtils.getPrefixedInt(fileText, "// RUNTIME:") != null;
final String[] expected = completionUtils.itemsShouldExist(fileText);
final String[] unexpected = completionUtils.itemsShouldAbsent(fileText);
Integer itemsNumber = completionUtils.getExpectedNumber(fileText);
try {
if (withKotlinRuntime) {
configureWithKotlinRuntime();
}
assertTrue("Should be some assertions about completion", expected.length != 0 || unexpected.length != 0 || itemsNumber != null);
Integer completionTime = completionUtils.getExecutionTime(fileText);
assertContainsItems(expected);
assertNotContainItems(unexpected);
complete(completionTime == null ? 1 : completionTime);
if (itemsNumber != null) {
assertEquals(itemsNumber.intValue(), myItems.length);
final String[] expected = completionUtils.itemsShouldExist(fileText);
final String[] unexpected = completionUtils.itemsShouldAbsent(fileText);
Integer itemsNumber = completionUtils.getExpectedNumber(fileText);
assertTrue("Should be some assertions about completion", expected.length != 0 || unexpected.length != 0 || itemsNumber != null);
assertContainsItems(expected);
assertNotContainItems(unexpected);
if (itemsNumber != null) {
assertEquals(itemsNumber.intValue(), myItems.length);
}
}
finally {
if (withKotlinRuntime) {
unConfigureKotlinRuntime();
}
}
} catch (Exception e) {
throw new AssertionError(e);
}
}
protected static void configureWithKotlinRuntime() {
final ModuleRootManager rootManager = ModuleRootManager.getInstance(getModule());
final ModifiableRootModel rootModel = rootManager.getModifiableModel();
rootModel.setSdk(getFullJavaJDK());
JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE.configureModule(getModule(), rootModel, null);
rootModel.commit();
}
protected void unConfigureKotlinRuntime() {
final ModuleRootManager rootManager = ModuleRootManager.getInstance(getModule());
final ModifiableRootModel rootModel = rootManager.getModifiableModel();
rootModel.setSdk(getProjectJDK());
JetWithJdkAndRuntimeLightProjectDescriptor.unConfigureModule(rootModel);
rootModel.commit();
}
@Override
protected Sdk getProjectJDK() {
return PluginTestCaseBase.jdkFromIdeaHome();
}
protected static Sdk getFullJavaJDK() {
return JavaSdk.getInstance().createJdk("JDK", SystemUtils.getJavaHome().getAbsolutePath());
}
@Override
protected void complete(final int time) {
new CodeCompletionHandlerBase(type, false, false, true).invokeCompletion(getProject(), getEditor(), time, false);
@@ -23,10 +23,30 @@ import org.jetbrains.jet.plugin.PluginTestCaseBase;
*/
public class JetMultifileBasicCompletionTest extends JetCompletionMultiTestBase {
public void testDoNotCompleteWithConstraints() {
doFileTest(2);
}
public void testTopLevelFunction() throws Exception {
doFileTest(2);
}
public void todotestExtensionFunctionOnUnresolved() throws Exception {
doFileTest(2);
}
public void testExtensionOnNullable() throws Exception {
doFileTest(2);
}
public void todotestExtensionProperty() throws Exception {
doFileTest(2);
}
public void testNotImportedExtensionFunction() throws Exception {
doFileTest(2);
}
public void testExtensionFunction() throws Exception {
// TODO: fix and uncomment
// doFileTest();
@@ -26,6 +26,10 @@ import java.io.File;
*/
public class CompletionMultifileHandlerTest extends CompletionTestCase {
public void testExtensionFunctions() throws Exception {
doTest();
}
public void testTopLevelFunctionImport() throws Exception {
doTest();
}
@@ -21,14 +21,14 @@ import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightProjectDescriptor;
import org.apache.commons.lang.SystemUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.ForTestCompileStdlib;
/**
@@ -52,11 +52,25 @@ public class JetWithJdkAndRuntimeLightProjectDescriptor implements LightProjectD
}
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @Nullable ContentEntry contentEntry) {
Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("ktl").getModifiableModel();
VirtualFile cd = JarFileSystem.getInstance().findFileByPath(ForTestCompileStdlib.stdlibJarForTests() + "!/");
assert cd != null;
modifiableModel.addRoot(cd, OrderRootType.CLASSES);
modifiableModel.commit();
}
public static void unConfigureModule(@NotNull ModifiableRootModel model) {
for (OrderEntry orderEntry : model.getOrderEntries()) {
if (orderEntry instanceof LibraryOrderEntry) {
LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry) orderEntry;
Library library = libraryOrderEntry.getLibrary();
if (library != null && library.getName().equals("ktl")) {
model.getModuleLibraryTable().removeLibrary(library);
break;
}
}
}
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="js.translator" />
<orderEntry type="module" module-name="compiler-tests" />
@@ -31,32 +31,32 @@ public final class ArrayListTest extends JavaClassesTest {
}
public void testEmptyList() throws Exception {
testFooBoxIsTrue("emptyList.kt");
checkFooBoxIsTrue("emptyList.kt");
}
public void testAccess() throws Exception {
testFooBoxIsTrue("access.kt");
checkFooBoxIsTrue("access.kt");
}
public void testIsEmpty() throws Exception {
testFooBoxIsTrue("isEmpty.kt");
checkFooBoxIsTrue("isEmpty.kt");
}
public void testArrayAccess() throws Exception {
testFooBoxIsTrue("arrayAccess.kt");
checkFooBoxIsTrue("arrayAccess.kt");
}
public void testIterate() throws Exception {
testFooBoxIsTrue("iterate.kt");
checkFooBoxIsTrue("iterate.kt");
}
public void testRemove() throws Exception {
testFooBoxIsTrue("remove.kt");
checkFooBoxIsTrue("remove.kt");
}
public void testIndexOOB() throws Exception {
try {
testFooBoxIsTrue("indexOOB.kt");
checkFooBoxIsTrue("indexOOB.kt");
fail();
} catch (JavaScriptException e) {
@@ -33,27 +33,27 @@ public final class ClassInheritanceTest extends TranslationTest {
}
public void testMethodOverride() throws Exception {
testFooBoxIsTrue("methodOverride.kt");
checkFooBoxIsTrue("methodOverride.kt");
}
public void testInitializationOrder() throws Exception {
testFooBoxIsTrue("initializationOrder.kt");
checkFooBoxIsTrue("initializationOrder.kt");
}
public void testComplexInitializationOrder() throws Exception {
testFooBoxIsTrue("complexInitializationOrder.kt");
checkFooBoxIsTrue("complexInitializationOrder.kt");
}
public void testValuePassedToAncestorConstructor() throws Exception {
testFooBoxIsTrue("valuePassedToAncestorConstructor.kt");
checkFooBoxIsTrue("valuePassedToAncestorConstructor.kt");
}
public void testBaseClassDefinedAfterDerived() throws Exception {
testFooBoxIsTrue("baseClassDefinedAfterDerived.kt");
checkFooBoxIsTrue("baseClassDefinedAfterDerived.kt");
}
public void testDefinitionOrder() throws Exception {
testFooBoxIsTrue("definitionOrder.kt");
checkFooBoxIsTrue("definitionOrder.kt");
}
}
@@ -33,7 +33,7 @@ public class ConditionalTest extends AbstractExpressionTest {
public void testIfElseAsExpressionWithThrow() throws Exception {
try {
testFooBoxIsTrue("ifAsExpressionWithThrow.kt");
checkFooBoxIsTrue("ifAsExpressionWithThrow.kt");
fail();
} catch (JavaScriptException e) {
@@ -28,38 +28,38 @@ public final class ExtensionFunctionTest extends TranslationTest {
}
public void testIntExtension() throws Exception {
testFooBoxIsTrue("intExtension.kt");
checkFooBoxIsTrue("intExtension.kt");
}
public void testExtensionWithImplicitReceiver() throws Exception {
testFooBoxIsTrue("extensionWithImplicitReceiver.kt");
checkFooBoxIsTrue("extensionWithImplicitReceiver.kt");
}
public void testExtensionFunctionOnExpression() throws Exception {
testFooBoxIsTrue("extensionFunctionOnExpression.kt");
checkFooBoxIsTrue("extensionFunctionOnExpression.kt");
}
public void testExtensionUsedInsideClass() throws Exception {
testFooBoxIsTrue("extensionUsedInsideClass.kt");
checkFooBoxIsTrue("extensionUsedInsideClass.kt");
}
public void testVirtualExtension() throws Exception {
testFooBoxIsTrue("virtualExtension.kt");
checkFooBoxIsTrue("virtualExtension.kt");
}
public void testVirtualExtensionOverride() throws Exception {
testFooBoxIsTrue("virtualExtensionOverride.kt");
checkFooBoxIsTrue("virtualExtensionOverride.kt");
}
public void testExtensionLiteralPassedToFunction() throws Exception {
testFooBoxIsTrue("extensionLiteralPassedToFunction.kt");
checkFooBoxIsTrue("extensionLiteralPassedToFunction.kt");
}
public void testExtensionInsideFunctionLiteral() throws Exception {
testFooBoxIsTrue("extensionInsideFunctionLiteral.kt");
checkFooBoxIsTrue("extensionInsideFunctionLiteral.kt");
}
public void testGenericExtension() throws Exception {
testFooBoxIsOk("generic.kt");
checkFooBoxIsOk("generic.kt");
}
}
@@ -28,14 +28,14 @@ public final class ExtensionPropertyTest extends TranslationTest {
}
public void testSimplePropertyWithGetter() throws Exception {
testFooBoxIsTrue("simplePropertyWithGetter.kt");
checkFooBoxIsTrue("simplePropertyWithGetter.kt");
}
public void testPropertyWithGetterAndSetter() throws Exception {
testFooBoxIsTrue("propertyWithGetterAndSetter.kt");
checkFooBoxIsTrue("propertyWithGetterAndSetter.kt");
}
public void testAbsExtension() throws Exception {
testFooBoxIsTrue("absExtension.kt");
checkFooBoxIsTrue("absExtension.kt");
}
}
@@ -29,10 +29,10 @@ public final class ForTest extends AbstractExpressionTest {
}
public void testForIteratesOverArray() throws Exception {
testFooBoxIsTrue("forIteratesOverArray.kt");
checkFooBoxIsTrue("forIteratesOverArray.kt");
}
public void testForOnEmptyArray() throws Exception {
testFooBoxIsTrue("forOnEmptyArray.kt");
checkFooBoxIsTrue("forOnEmptyArray.kt");
}
}
@@ -29,35 +29,35 @@ public class FunctionTest extends AbstractExpressionTest {
}
public void testFunctionUsedBeforeDeclaration() throws Exception {
testFooBoxIsTrue("functionUsedBeforeDeclaration.kt");
checkFooBoxIsTrue("functionUsedBeforeDeclaration.kt");
}
public void testFunctionWithTwoParametersCall() throws Exception {
testFooBoxIsTrue("functionWithTwoParametersCall.kt");
checkFooBoxIsTrue("functionWithTwoParametersCall.kt");
}
public void testFunctionLiteral() throws Exception {
testFooBoxIsTrue("functionLiteral.kt");
checkFooBoxIsTrue("functionLiteral.kt");
}
public void testAdderClosure() throws Exception {
testFooBoxIsTrue("adderClosure.kt");
checkFooBoxIsTrue("adderClosure.kt");
}
public void testLoopClosure() throws Exception {
testFooBoxIsTrue("loopClosure.kt");
checkFooBoxIsTrue("loopClosure.kt");
}
public void testFunctionLiteralAsParameter() throws Exception {
testFooBoxIsTrue("functionLiteralAsParameter.kt");
checkFooBoxIsTrue("functionLiteralAsParameter.kt");
}
public void testClosureWithParameter() throws Exception {
testFooBoxIsOk("closureWithParameter.kt");
checkFooBoxIsOk("closureWithParameter.kt");
}
public void testClosureWithParameterAndBoxing() throws Exception {
testFooBoxIsOk("closureWithParameterAndBoxing.jet");
checkFooBoxIsOk("closureWithParameterAndBoxing.jet");
}
public void testEnclosingThis() throws Exception {
@@ -66,32 +66,32 @@ public class FunctionTest extends AbstractExpressionTest {
public void testImplicitItParameter() throws Exception {
testFooBoxIsTrue("implicitItParameter.kt");
checkFooBoxIsTrue("implicitItParameter.kt");
}
public void testDefaultParameters() throws Exception {
testFooBoxIsTrue("defaultParameters.kt");
checkFooBoxIsTrue("defaultParameters.kt");
}
public void testFunctionLiteralAsLastParameter() throws Exception {
testFooBoxIsTrue("functionLiteralAsLastParameter.kt");
checkFooBoxIsTrue("functionLiteralAsLastParameter.kt");
}
public void testNamedArguments() throws Exception {
testFooBoxIsTrue("namedArguments.kt");
checkFooBoxIsTrue("namedArguments.kt");
}
public void testExpressionAsFunction() throws Exception {
testFooBoxIsTrue("expressionAsFunction.kt");
checkFooBoxIsTrue("expressionAsFunction.kt");
}
public void testVararg() throws Exception {
testFooBoxIsTrue("vararg.kt");
checkFooBoxIsTrue("vararg.kt");
}
@@ -104,6 +104,6 @@ public class FunctionTest extends AbstractExpressionTest {
}
public void testFunctionInsideFunction() throws Exception {
testFooBoxIsTrue("functionInsideFunction.kt");
checkFooBoxIsTrue("functionInsideFunction.kt");
}
}
@@ -55,7 +55,7 @@ public final class KotlinLibTest extends TranslationTest {
final Map<String, Class<? extends Scriptable>> propertyToType
= new HashMap<String, Class<? extends Scriptable>>();
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("trait.js")),
new RhinoPropertyTypesChecker("foo", propertyToType));
new RhinoPropertyTypesChecker("foo", propertyToType));
}
@@ -63,56 +63,61 @@ public final class KotlinLibTest extends TranslationTest {
final Map<String, Class<? extends Scriptable>> propertyToType
= new HashMap<String, Class<? extends Scriptable>>();
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("namespace.js")),
new RhinoPropertyTypesChecker("foo", propertyToType));
new RhinoPropertyTypesChecker("foo", propertyToType));
}
//
// TODO:Refactor calls to function result checker with test
public void testNamespaceHasDeclaredFunction() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("namespace.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
public void testNamespaceHasDeclaredClasses() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("namespaceWithClasses.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
public void testIsSameType() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("isSameType.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
public void testIsAncestorType() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("isAncestorType.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
public void testIsComplexTest() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("isComplexTest.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
public void testCommaExpression() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("commaExpression.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
public void testArray() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("array.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
public void testHashMap() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("hashMap.js")),
new RhinoFunctionResultChecker("test", true));
new RhinoFunctionResultChecker("test", true));
}
@Override
protected boolean shouldCreateOut() {
return false;
}
}
@@ -36,11 +36,11 @@ public final class MiscTest extends AbstractExpressionTest {
public void testIntRange() throws Exception {
// checkOutput("intRange.kt", " ");
testFooBoxIsTrue("intRange.kt");
checkFooBoxIsTrue("intRange.kt");
}
public void testSafecallComputesExpressionOnlyOnce() throws Exception {
testFooBoxIsTrue("safecallComputesExpressionOnlyOnce.kt");
checkFooBoxIsTrue("safecallComputesExpressionOnlyOnce.kt");
}
}
@@ -29,15 +29,15 @@ public final class MultiFileTest extends TranslationTest {
}
public void testFunctionsVisibleFromOtherFile() throws Exception {
testFooBoxIsTrue("functionsVisibleFromOtherFile");
checkFooBoxIsTrue("functionsVisibleFromOtherFile");
}
public void testClassesInheritedFromOtherFile() throws Exception {
testFooBoxIsTrue("classesInheritedFromOtherFile");
checkFooBoxIsTrue("classesInheritedFromOtherFile");
}
@Override
public void testFooBoxIsTrue(String dirName) throws Exception {
public void checkFooBoxIsTrue(String dirName) throws Exception {
testMultiFile(dirName, "foo", "box", true);
}
}
@@ -28,15 +28,15 @@ public class MultiNamespaceTest extends TranslationTest {
}
public void testFunctionsVisibleFromOtherNamespace() throws Exception {
testFooBoxIsTrue("functionsVisibleFromOtherNamespace");
checkFooBoxIsTrue("functionsVisibleFromOtherNamespace");
}
public void testClassesInheritedFromOtherNamespace() throws Exception {
testFooBoxIsTrue("classesInheritedFromOtherNamespace");
checkFooBoxIsTrue("classesInheritedFromOtherNamespace");
}
@Override
public void testFooBoxIsTrue(String dirName) throws Exception {
public void checkFooBoxIsTrue(String dirName) throws Exception {
testMultiFile(dirName, "foo", "box", true);
}
}
@@ -29,6 +29,6 @@ public final class NameClashesTest extends TranslationTest {
}
public void testMethodOverload() throws Exception {
testFooBoxIsTrue("methodOverload.kt");
checkFooBoxIsTrue("methodOverload.kt");
}
}
@@ -30,16 +30,16 @@ public final class ObjectTest extends TranslationTest {
public void testObjectWithMethods() throws Exception {
testFooBoxIsTrue("objectWithMethods.kt");
checkFooBoxIsTrue("objectWithMethods.kt");
}
public void testObjectDeclaration() throws Exception {
testFooBoxIsTrue("objectDeclaration.kt");
checkFooBoxIsTrue("objectDeclaration.kt");
}
public void testObjectInMethod() throws Exception {
testFooBoxIsTrue("objectInMethod.kt");
checkFooBoxIsTrue("objectInMethod.kt");
}
}
@@ -30,79 +30,79 @@ public final class OperatorOverloadingTest extends TranslationTest {
public void testPlusOverload() throws Exception {
testFooBoxIsTrue("plusOverload.kt");
checkFooBoxIsTrue("plusOverload.kt");
}
public void testPostfixInc() throws Exception {
testFooBoxIsTrue("postfixIncOverload.kt");
checkFooBoxIsTrue("postfixIncOverload.kt");
}
public void testPrefixDecOverload() throws Exception {
testFooBoxIsTrue("prefixDecOverload.kt");
checkFooBoxIsTrue("prefixDecOverload.kt");
}
public void testPrefixIncReturnsCorrectValue() throws Exception {
testFooBoxIsTrue("prefixIncReturnsCorrectValue.kt");
checkFooBoxIsTrue("prefixIncReturnsCorrectValue.kt");
}
public void testOverloadedCallOnProperty() throws Exception {
testFooBoxIsTrue("overloadedCallOnProperty.kt");
checkFooBoxIsTrue("overloadedCallOnProperty.kt");
}
public void testPostfixOnProperty() throws Exception {
testFooBoxIsTrue("postfixOnProperty.kt");
checkFooBoxIsTrue("postfixOnProperty.kt");
}
public void testOperatorOverloadOnPropertyCallGetterAndSetterOnlyOnce() throws Exception {
testFooBoxIsTrue("operatorOverloadOnPropertyCallGetterAndSetterOnlyOnce.kt");
checkFooBoxIsTrue("operatorOverloadOnPropertyCallGetterAndSetterOnlyOnce.kt");
}
public void testUnaryOnIntProperty() throws Exception {
testFooBoxIsTrue("unaryOnIntProperty.kt");
checkFooBoxIsTrue("unaryOnIntProperty.kt");
}
public void testUnaryOnIntPropertyAsStatement() throws Exception {
testFooBoxIsTrue("unaryOnIntProperty2.kt");
checkFooBoxIsTrue("unaryOnIntProperty2.kt");
}
public void testBinaryDivOverload() throws Exception {
testFooBoxIsTrue("binaryDivOverload.kt");
checkFooBoxIsTrue("binaryDivOverload.kt");
}
public void testPlusAssignNoReassign() throws Exception {
testFooBoxIsTrue("plusAssignNoReassign.kt");
checkFooBoxIsTrue("plusAssignNoReassign.kt");
}
public void testNotOverload() throws Exception {
testFooBoxIsTrue("notOverload.kt");
checkFooBoxIsTrue("notOverload.kt");
}
public void testCompareTo() throws Exception {
testFooBoxIsTrue("compareTo.kt");
checkFooBoxIsTrue("compareTo.kt");
}
public void testPlusAndMinusAsAnExpression() throws Exception {
testFooBoxIsTrue("plusAndMinusAsAnExpression.kt");
checkFooBoxIsTrue("plusAndMinusAsAnExpression.kt");
}
public void testUsingModInCaseModAssignNotAvailable() throws Exception {
testFooBoxIsTrue("usingModInCaseModAssignNotAvailable.kt");
checkFooBoxIsTrue("usingModInCaseModAssignNotAvailable.kt");
}
public void testOverloadPlusAssignArrayList() throws Exception {
testFooBoxIsOk("overloadPlusAssignArrayList.kt");
checkFooBoxIsOk("overloadPlusAssignArrayList.kt");
}
}
@@ -32,37 +32,37 @@ public final class PatternMatchingTest extends TranslationTest {
public void testWhenType() throws Exception {
testFooBoxIsTrue("whenType.kt");
checkFooBoxIsTrue("whenType.kt");
}
public void testWhenNotType() throws Exception {
testFooBoxIsTrue("whenNotType.kt");
checkFooBoxIsTrue("whenNotType.kt");
}
public void testWhenExecutesOnlyOnce() throws Exception {
testFooBoxIsTrue("whenExecutesOnlyOnce.kt");
checkFooBoxIsTrue("whenExecutesOnlyOnce.kt");
}
public void testWhenValue() throws Exception {
testFooBoxIsTrue("whenValue.kt");
checkFooBoxIsTrue("whenValue.kt");
}
public void testWhenNotValue() throws Exception {
testFooBoxIsTrue("whenNotValue.kt");
checkFooBoxIsTrue("whenNotValue.kt");
}
public void testWhenValueOrType() throws Exception {
testFooBoxIsTrue("whenValueOrType.kt");
checkFooBoxIsTrue("whenValueOrType.kt");
}
public void testWhenWithIf() throws Exception {
testFooBoxIsTrue("whenWithIf.kt");
checkFooBoxIsTrue("whenWithIf.kt");
}
@@ -72,17 +72,17 @@ public final class PatternMatchingTest extends TranslationTest {
public void testMatchNullableType() throws Exception {
testFooBoxIsTrue("matchNullableType.kt");
checkFooBoxIsTrue("matchNullableType.kt");
}
public void testWhenAsExpression() throws Exception {
testFooBoxIsTrue("whenAsExpression.kt");
checkFooBoxIsTrue("whenAsExpression.kt");
}
public void whenAsExpressionWithThrow() throws Exception {
try {
testFooBoxIsTrue("whenAsExpressionWithThrow.kt");
checkFooBoxIsTrue("whenAsExpressionWithThrow.kt");
fail();
} catch (JavaScriptException e) {
}
@@ -30,12 +30,12 @@ public final class PropertyAccessTest extends TranslationTest {
public void testAccessToInstanceProperty() throws Exception {
testFooBoxIsTrue("accessToInstanceProperty.kt");
checkFooBoxIsTrue("accessToInstanceProperty.kt");
}
public void testTwoClassesWithProperties() throws Exception {
testFooBoxIsTrue("twoClassesWithProperties.kt");
checkFooBoxIsTrue("twoClassesWithProperties.kt");
}
@@ -45,55 +45,55 @@ public final class PropertyAccessTest extends TranslationTest {
public void testCustomGetter() throws Exception {
testFooBoxIsTrue("customGetter.kt");
checkFooBoxIsTrue("customGetter.kt");
}
public void testCustomSetter() throws Exception {
testFooBoxIsTrue("customSetter.kt");
checkFooBoxIsTrue("customSetter.kt");
}
public void testSafeCall() throws Exception {
testFooBoxIsTrue("safeCall.kt");
checkFooBoxIsTrue("safeCall.kt");
}
//TODO: place safecalls under distinkt category
public void testSafeCallReturnsNullIfFails() throws Exception {
testFooBoxIsTrue("safeCallReturnsNullIfFails.kt");
checkFooBoxIsTrue("safeCallReturnsNullIfFails.kt");
}
public void testNamespacePropertyInitializer() throws Exception {
testFooBoxIsTrue("namespacePropertyInitializer.kt");
checkFooBoxIsTrue("namespacePropertyInitializer.kt");
}
public void testNamespacePropertySet() throws Exception {
testFooBoxIsTrue("namespacePropertySet.kt");
checkFooBoxIsTrue("namespacePropertySet.kt");
}
public void testNamespaceCustomAccessors() throws Exception {
testFooBoxIsTrue("namespaceCustomAccessors.kt");
checkFooBoxIsTrue("namespaceCustomAccessors.kt");
}
public void testClassUsesNamespaceProperties() throws Exception {
testFooBoxIsTrue("classUsesNamespaceProperties.kt");
checkFooBoxIsTrue("classUsesNamespaceProperties.kt");
}
public void testSafeAccess() throws Exception {
testFooBoxIsTrue("safeAccess.kt");
checkFooBoxIsTrue("safeAccess.kt");
}
public void testSafeExtensionFunctionCall() throws Exception {
testFooBoxIsOk("safeExtensionFunctionCall.kt");
checkFooBoxIsOk("safeExtensionFunctionCall.kt");
}
public void testExtensionLiteralSafeCall() throws Exception {
testFooBoxIsTrue("extensionLiteralSafeCall.kt");
checkFooBoxIsTrue("extensionLiteralSafeCall.kt");
}
}
@@ -29,10 +29,10 @@ public class RTTITest extends TranslationTest {
}
public void testIsSameClass() throws Exception {
testFooBoxIsTrue("isSameClass.kt");
checkFooBoxIsTrue("isSameClass.kt");
}
public void testNotIsOtherClass() throws Exception {
testFooBoxIsTrue("notIsOtherClass.kt");
checkFooBoxIsTrue("notIsOtherClass.kt");
}
}
@@ -30,20 +30,20 @@ public final class RangeTest extends TranslationTest {
public void testExplicitRange() throws Exception {
testFooBoxIsTrue("explicitRange.kt");
checkFooBoxIsTrue("explicitRange.kt");
}
public void testRangeSugarSyntax() throws Exception {
testFooBoxIsTrue("rangeSugarSyntax.kt");
checkFooBoxIsTrue("rangeSugarSyntax.kt");
}
public void testIntInRange() throws Exception {
testFooBoxIsTrue("intInRange.kt");
checkFooBoxIsTrue("intInRange.kt");
}
public void testIteratingOverRanges() throws Exception {
testFooBoxIsTrue("iteratingOverRanges.kt");
checkFooBoxIsTrue("iteratingOverRanges.kt");
}
}
@@ -29,7 +29,7 @@ public final class SimpleTestSuite extends UsefulTestCase {
return Suite.suiteForDirectory("simple/", new Suite.SingleFileTester() {
@Override
public void performTest(@NotNull Suite test, @NotNull String filename) throws Exception {
test.testFooBoxIsTrue(filename);
test.checkFooBoxIsTrue(filename);
}
});
}
@@ -29,38 +29,38 @@ public class StandardClassesTest extends TranslationTest {
public void testArray() throws Exception {
testFooBoxIsTrue("array.kt");
checkFooBoxIsTrue("array.kt");
}
public void testArrayAccess() throws Exception {
testFooBoxIsTrue("arrayAccess.kt");
checkFooBoxIsTrue("arrayAccess.kt");
}
public void testArrayIsFilledWithNulls() throws Exception {
testFooBoxIsTrue("arrayIsFilledWithNulls.kt");
checkFooBoxIsTrue("arrayIsFilledWithNulls.kt");
}
public void testArrayFunctionConstructor() throws Exception {
testFooBoxIsTrue("arrayFunctionConstructor.kt");
checkFooBoxIsTrue("arrayFunctionConstructor.kt");
}
public void testArraySize() throws Exception {
testFooBoxIsTrue("arraySize.kt");
checkFooBoxIsTrue("arraySize.kt");
}
//TODO: this feature in not supported for some time
//TODO: support it. Probably configurable.
// (expected = JavaScriptException.class)
// public void arrayThrowsExceptionOnOOBaccess() throws Exception {
// testFooBoxIsTrue("arrayThrowsExceptionOnOOBaccess.kt");
// checkFooBoxIsTrue("arrayThrowsExceptionOnOOBaccess.kt");
// }
public void testArraysIterator() throws Exception {
testFooBoxIsTrue("arraysIterator.kt");
checkFooBoxIsTrue("arraysIterator.kt");
}
}
@@ -29,11 +29,11 @@ public class StringTest extends AbstractExpressionTest {
}
public void testStringConstant() throws Exception {
testFooBoxIsTrue("stringConstant.kt");
checkFooBoxIsTrue("stringConstant.kt");
}
public void testStringAssignment() throws Exception {
testFooBoxIsTrue("stringAssignment.kt");
checkFooBoxIsTrue("stringAssignment.kt");
}
public void testIntInTemplate() throws Exception {
@@ -49,6 +49,6 @@ public class StringTest extends AbstractExpressionTest {
}
public void testToStringMethod() throws Exception {
testFooBoxIsTrue("objectToStringCallInTemplate.kt");
checkFooBoxIsTrue("objectToStringCallInTemplate.kt");
}
}
@@ -35,6 +35,7 @@ public final class Suite extends TranslationTest {
this.name = testName;
this.tester = tester;
this.testMain = suiteDirName;
setName(name);
}
public Suite() {
@@ -46,10 +47,15 @@ public final class Suite extends TranslationTest {
});
}
// //NOTE: just to avoid warning
//NOTE: just to avoid warning
public void testNothing() {
}
@Override
protected boolean shouldCreateOut() {
return false;
}
@Override
protected String mainDirectory() {
return testMain;
@@ -62,13 +68,15 @@ public final class Suite extends TranslationTest {
public static Test suiteForDirectory(@NotNull final String mainName, @NotNull final SingleFileTester testMethod) {
return TranslatorTestCaseBuilder.suiteForDirectory(TranslationTest.TEST_FILES,
mainName + casesDirectoryName(), true, new TranslatorTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String name) {
return (new Suite(name, mainName, testMethod));
}
});
mainName + casesDirectoryName(),
true,
new TranslatorTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String name) {
return (new Suite(name, mainName, testMethod));
}
});
}
protected static interface SingleFileTester {
@@ -30,41 +30,41 @@ public final class TraitTest extends TranslationTest {
public void testTraitAddsFunctionsToClass() throws Exception {
testFooBoxIsTrue("traitAddsFunctionsToClass.kt");
checkFooBoxIsTrue("traitAddsFunctionsToClass.kt");
}
public void testClassDerivesFromClassAndTrait() throws Exception {
testFooBoxIsTrue("classDerivesFromClassAndTrait.kt");
checkFooBoxIsTrue("classDerivesFromClassAndTrait.kt");
}
public void testClassDerivesFromTraitAndClass() throws Exception {
testFooBoxIsTrue("classDerivesFromTraitAndClass.kt");
checkFooBoxIsTrue("classDerivesFromTraitAndClass.kt");
}
public void testExample() throws Exception {
testFooBoxIsTrue("example.kt");
checkFooBoxIsTrue("example.kt");
}
public void testTraitExtendsTrait() throws Exception {
testFooBoxIsTrue("traitExtendsTrait.kt");
checkFooBoxIsTrue("traitExtendsTrait.kt");
}
public void testTraitExtendsTwoTraits() throws Exception {
testFooBoxIsTrue("traitExtendsTwoTraits.kt");
checkFooBoxIsTrue("traitExtendsTwoTraits.kt");
}
public void testFunDelegation() throws Exception {
testFooBoxIsOk("funDelegation.jet");
checkFooBoxIsOk("funDelegation.jet");
}
public void testDefinitionOrder() throws Exception {
testFooBoxIsTrue("definitionOrder.kt");
checkFooBoxIsTrue("definitionOrder.kt");
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.k2js.test;
import com.google.dart.compiler.backend.js.ast.JsProgram;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.k2js.facade.K2JSTranslator;
@@ -27,9 +28,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -44,7 +42,8 @@ import static org.jetbrains.k2js.utils.JetFileUtils.createPsiFileList;
*/
public abstract class TranslationTest extends BaseTest {
public final static String TEST_FILES = "js.translator/testFiles/";
private static final boolean DELETE_OUT = false;
public static final String TEST_FILES = "js.translator/testFiles/";
private static final String CASES = "cases/";
private static final String OUT = "out/";
private static final String KOTLIN_JS_LIB = TEST_FILES + "kotlin_lib.js";
@@ -63,6 +62,32 @@ public abstract class TranslationTest extends BaseTest {
K2JSTranslator.saveProgramToFile(outputFile, program);
}
@Override
protected void setUp() throws Exception {
super.setUp();
if (!shouldCreateOut()) {
return;
}
File outDir = new File(getOutputPath());
assert (!outDir.exists() || outDir.isDirectory()) : "If out already exists it should be a directory.";
if (!outDir.exists()) {
boolean success = outDir.mkdir();
assert success;
}
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
if (!shouldCreateOut() || !DELETE_OUT) {
return;
}
File outDir = new File(getOutputPath());
assert outDir.exists();
boolean success = FileUtil.delete(outDir);
assert success;
}
protected static String kotlinLibraryPath() {
return KOTLIN_JS_LIB;
}
@@ -116,6 +141,10 @@ public abstract class TranslationTest extends BaseTest {
new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult));
}
protected boolean shouldCreateOut() {
return true;
}
protected void translateFile(String filename) throws Exception {
translateFile(getInputFilePath(filename),
getOutputFilePath(filename));
@@ -126,7 +155,7 @@ public abstract class TranslationTest extends BaseTest {
File dir = new File(dirPath);
List<String> fullFilePaths = new ArrayList<String>();
for (String fileName : dir.list()) {
fullFilePaths.add(getInputFilePath(dirName) + "\\" + fileName);
fullFilePaths.add(getInputFilePath(dirName) + "/" + fileName);
}
assert dir.isDirectory();
traslateFiles(fullFilePaths,
@@ -158,13 +187,17 @@ public abstract class TranslationTest extends BaseTest {
return getExpectedPath() + testName + ".out";
}
protected void runFileWithRhino(String inputFile, Context context, Scriptable scope) throws Exception {
protected static void runFileWithRhino(String inputFile, Context context, Scriptable scope) throws Exception {
FileReader reader = new FileReader(inputFile);
context.evaluateReader(scope, reader, inputFile, 1, null);
reader.close();
try {
context.evaluateReader(scope, reader, inputFile, 1, null);
} finally {
reader.close();
}
}
protected void runRhinoTest(List<String> fileNames, RhinoResultChecker checker) throws Exception {
protected static void runRhinoTest(@NotNull List<String> fileNames,
@NotNull RhinoResultChecker checker) throws Exception {
Context context = Context.enter();
Scriptable scope = context.initStandardObjects();
for (String filename : fileNames) {
@@ -174,11 +207,11 @@ public abstract class TranslationTest extends BaseTest {
Context.exit();
}
public void testFooBoxIsTrue(String filename) throws Exception {
public void checkFooBoxIsTrue(String filename) throws Exception {
testFunctionOutput(filename, "foo", "box", true);
}
public void testFooBoxIsOk(String filename) throws Exception {
public void checkFooBoxIsOk(String filename) throws Exception {
testFunctionOutput(filename, "foo", "box", "OK");
}
@@ -188,21 +221,16 @@ public abstract class TranslationTest extends BaseTest {
new RhinoSystemOutputChecker(expectedResult, Arrays.asList(args)));
}
protected void testWithMain(String testName, String testId, String... args) throws Exception {
protected void performTestWithMain(String testName, String testId, String... args) throws Exception {
checkOutput(testName + ".kt", readFile(expected(testName + testId)), args);
}
private static String readFile(String path) throws IOException {
FileInputStream stream = new FileInputStream(new File(path));
try {
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
/* Instead of using default, pass in a decoder. */
return Charset.defaultCharset().decode(bb).toString();
return FileUtil.loadTextAndClose(stream);
} finally {
stream.close();
}
}
}
@@ -53,6 +53,7 @@ public abstract class TranslatorTestCaseBuilder {
public static TestSuite suiteForDirectory(String baseDataDir, @NotNull final String dataPath, boolean recursive,
final FilenameFilter filter, @NotNull NamedTestFactory factory) {
TestSuite suite = new TestSuite(dataPath);
suite.setName(dataPath);
appendTestsInDirectory(baseDataDir, dataPath, recursive, filter, factory, suite);
return suite;
}
@@ -75,7 +76,8 @@ public abstract class TranslatorTestCaseBuilder {
return extensionFilter.accept(file, s) && filter.accept(file, s);
}
};
} else {
}
else {
resultFilter = extensionFilter;
}
File dir = new File(baseDataDir + dataPath);
@@ -29,11 +29,11 @@ public final class TupleTest extends TranslationTest {
}
public void testTwoElements() throws Exception {
testFooBoxIsTrue("twoElements.kt");
checkFooBoxIsTrue("twoElements.kt");
}
public void testMultipleMembers() throws Exception {
testFooBoxIsTrue("multipleMembers.kt");
checkFooBoxIsTrue("multipleMembers.kt");
}
@@ -29,22 +29,22 @@ public final class WebDemoExamples2Test extends TranslationTest {
}
public void testBottles() throws Exception {
testWithMain("bottles", "2", "2");
testWithMain("bottles", "");
performTestWithMain("bottles", "2", "2");
performTestWithMain("bottles", "");
}
public void testLife() throws Exception {
testWithMain("life", "", "2");
performTestWithMain("life", "", "2");
}
public void testBuilder() throws Exception {
testWithMain("builder", "");
testWithMain("builder", "1", "over9000");
performTestWithMain("builder", "");
performTestWithMain("builder", "1", "over9000");
}
//TODO: comparator LinkedList dependencies
// @Test
// public void maze() throws Exception {
// testWithMain("maze", "");
// performTestWithMain("maze", "");
// }
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.Configuration;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.StandardConfiguration;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -40,9 +39,9 @@ import java.util.List;
/**
* @author Pavel Talanov
*/
public final class Analyzer {
public final class AnalyzerFacade {
private Analyzer() {
private AnalyzerFacade() {
}
@NotNull
@@ -58,10 +57,10 @@ public final class Analyzer {
@NotNull Config config) {
Project project = config.getProject();
return AnalyzingUtils.analyzeFiles(project,
JsConfiguration.jsLibConfiguration(project),
withJsLibAdded(files, config),
notLibFiles(config.getLibFiles()),
JetControlFlowDataTraceFactory.EMPTY);
JsConfiguration.jsLibConfiguration(project),
withJsLibAdded(files, config),
notLibFiles(config.getLibFiles()),
JetControlFlowDataTraceFactory.EMPTY);
}
private static void checkForErrors(@NotNull List<JetFile> allFiles, @NotNull BindingContext bindingContext) {
@@ -105,7 +104,6 @@ public final class Analyzer {
JetControlFlowDataTraceFactory.EMPTY,
bindingTraceContext,
semanticServices);
// return AnalyzerFacade.analyzeOneFileWithJavaIntegration(file, flowDataTraceFactory);
}
private static final class JsConfiguration implements Configuration {
@@ -23,7 +23,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.plugin.JetMainDetector;
import org.jetbrains.k2js.analyze.Analyzer;
import org.jetbrains.k2js.analyze.AnalyzerFacade;
import org.jetbrains.k2js.config.Config;
import org.jetbrains.k2js.config.IDEAConfig;
import org.jetbrains.k2js.generate.CodeGenerator;
@@ -61,8 +61,11 @@ public final class K2JSTranslator {
}
String callToMain = translator.generateCallToMain(fileWithMain, "");
FileWriter writer = new FileWriter(new File(outputPath));
writer.write(programCode + callToMain);
writer.close();
try {
writer.write(programCode + callToMain);
} finally {
writer.close();
}
}
public static void saveProgramToFile(@NotNull String outputFile, @NotNull JsProgram program) throws IOException {
@@ -79,6 +82,8 @@ public final class K2JSTranslator {
}
//TODO: refactor
//TODO: web demo related method
@SuppressWarnings("UnusedDeclaration")
@NotNull
public String translateStringWithCallToMain(@NotNull String programText, @NotNull String argumentsString) {
JetFile file = JetFileUtils.createPsiFile("test", programText, getProject());
@@ -103,18 +108,20 @@ public final class K2JSTranslator {
return generator.generateToString(program);
}
//TODO: relates to web demo
@SuppressWarnings("UnusedDeclaration")
@NotNull
public BindingContext analyzeProgramCode(@NotNull String programText) {
JetFile file = JetFileUtils.createPsiFile("test", programText, getProject());
return Analyzer.analyzeFiles(Arrays.asList(file), config);
return AnalyzerFacade.analyzeFiles(Arrays.asList(file), config);
}
@NotNull
public JsProgram generateProgram(@NotNull List<JetFile> filesToTranslate) {
JetStandardLibrary.initialize(config.getProject());
BindingContext bindingContext = Analyzer.analyzeFilesAndCheckErrors(filesToTranslate, config);
return Translation.generateAst(bindingContext, Analyzer.withJsLibAdded(filesToTranslate, config));
BindingContext bindingContext = AnalyzerFacade.analyzeFilesAndCheckErrors(filesToTranslate, config);
return Translation.generateAst(bindingContext, AnalyzerFacade.withJsLibAdded(filesToTranslate, config));
}
@@ -126,7 +133,7 @@ public final class K2JSTranslator {
}
@NotNull
private List<String> parseString(@NotNull String argumentString) {
private static List<String> parseString(@NotNull String argumentString) {
List<String> result = new ArrayList<String>();
StringTokenizer stringTokenizer = new StringTokenizer(argumentString);
while (stringTokenizer.hasMoreTokens()) {
@@ -19,8 +19,7 @@ package org.jetbrains.k2js.translate.context;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsScope;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
/**
* @author Pavel Talanov
@@ -80,7 +79,7 @@ public final class NamingScope {
String result = name;
while (true) {
JsName existingNameWithSameIdent = scope.findExistingName(result);
boolean isDuplicate = (existingNameWithSameIdent != null) && ownsName(scope, existingNameWithSameIdent);
boolean isDuplicate = (existingNameWithSameIdent != null) && JsAstUtils.ownsName(scope, existingNameWithSameIdent);
if (!isDuplicate) break;
@@ -90,17 +89,6 @@ public final class NamingScope {
return result;
}
//TODO: util?
private static boolean ownsName(@NotNull JsScope scope, @NotNull JsName name) {
Iterator<JsName> nameIterator = scope.getAllNames();
while (nameIterator.hasNext()) {
if (nameIterator.next() == name) {
return true;
}
}
return false;
}
@NotNull
public JsName declareTemporary() {
@@ -323,6 +323,7 @@ public final class StaticContext {
}
}
@NotNull
private NamingScope getEnclosingScope(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor);
return getScopeForDescriptor(containingDeclaration.getOriginal());
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.ArrayList;
import java.util.List;
@@ -165,10 +166,7 @@ public final class ClassTranslator extends AbstractTranslator {
}
propertyList.addAll(translatePropertiesAsConstructorParameters());
propertyList.addAll(declarationBodyVisitor.traverseClass(classDeclaration, context()));
//TODO: util?
JsObjectLiteral jsObjectLiteral = new JsObjectLiteral();
jsObjectLiteral.getPropertyInitializers().addAll(propertyList);
return jsObjectLiteral;
return JsAstUtils.newObjectLiteral(propertyList);
}
@NotNull
@@ -100,7 +100,7 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
}
@NotNull
private List<JsStatement> declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) {
private static List<JsStatement> declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) {
List<JsStatement> result = Lists.newArrayList();
for (NamespaceTranslator translator : namespaceTranslators) {
result.add(translator.getDeclarationStatement());
@@ -109,7 +109,7 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
}
@NotNull
private List<JsStatement> initializeStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) {
private static List<JsStatement> initializeStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) {
List<JsStatement> result = Lists.newArrayList();
for (NamespaceTranslator translator : namespaceTranslators) {
result.add(translator.getInitializeStatement());
@@ -29,8 +29,7 @@ import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
/**
* @author Pavel.Talanov
@@ -96,9 +95,6 @@ public final class NamespaceTranslator extends AbstractTranslator {
List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>();
propertyList.add(Translation.generateNamespaceInitializerMethod(descriptor, context()));
propertyList.addAll(new DeclarationBodyVisitor().traverseNamespace(descriptor, context()));
//TODO: make util, search for dups
JsObjectLiteral jsObjectLiteral = new JsObjectLiteral();
jsObjectLiteral.getPropertyInitializers().addAll(propertyList);
return jsObjectLiteral;
return newObjectLiteral(propertyList);
}
}
@@ -224,6 +224,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
return translateAsExpression(expression, context);
}
//NOTE: since JsWhile and JsDoWhile do not have an ancestor, cannot avoid duplication here
@Override
@NotNull
public JsNode visitWhileExpression(@NotNull JetWhileExpression expression, @NotNull TranslationContext context) {
@@ -128,15 +128,15 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull
private JsFunction createFunctionObject() {
if (isDeclaration()) {
return context().getFunctionObject(descriptor);
}
if (isLiteral()) {
//TODO: changing this piece of code to more natural "same as for declaration" results in life test failing
//TODO: must investigate
return new JsFunction(context().jsScope());
}
throw new AssertionError("Unsupported type of functionDeclaration.");
// if (isDeclaration()) {
return context().getFunctionObject(descriptor);
// }
// if (isLiteral()) {
// //TODO: changing this piece of code to more natural "same as for declaration" results in life test failing
// //TODO: must investigate
// return new JsFunction(context().jsScope());
// }
// throw new AssertionError("Unsupported type of functionDeclaration.");
}
private void translateBody() {

Some files were not shown because too many files have changed in this diff Show More