diff --git a/.gitignore b/.gitignore index 38f4c43e310..8648ec99ad4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ confluence/target out dist ideaSDK +PluginVerifier .idea/dictionaries/yozh.xml .idea/codeStyleSettings.xml .idea/workspace.xml diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml index 1dfe9e84ad8..4402d4e932c 100644 --- a/.idea/inspectionProfiles/idea_default.xml +++ b/.idea/inspectionProfiles/idea_default.xml @@ -49,6 +49,10 @@ + + diff --git a/.idea/libraries/asm.xml b/.idea/libraries/asm.xml index afc4bcc3b62..d343b26b416 100644 --- a/.idea/libraries/asm.xml +++ b/.idea/libraries/asm.xml @@ -1,7 +1,7 @@ - + diff --git a/.idea/libraries/js_libs.xml b/.idea/libraries/js_libs.xml index e42ca339692..e8a4874bfc6 100644 --- a/.idea/libraries/js_libs.xml +++ b/.idea/libraries/js_libs.xml @@ -3,6 +3,9 @@ + + + diff --git a/.idea/runConfigurations/Js_backend_tests.xml b/.idea/runConfigurations/Js_backend_tests.xml new file mode 100644 index 00000000000..011469a460a --- /dev/null +++ b/.idea/runConfigurations/Js_backend_tests.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TeamCityBuild.xml b/TeamCityBuild.xml index 8cdc6ea5f09..8b0f795a793 100644 --- a/TeamCityBuild.xml +++ b/TeamCityBuild.xml @@ -2,10 +2,15 @@ + + + + + @@ -55,13 +60,22 @@ - + - + + + + + + + + + + diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java b/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java index 64ff3cd9c77..81d7de736da 100644 --- a/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java @@ -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() { @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(); - } - } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 62d0e459c6b..9738e1958e2 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -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(); } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java index a1dd8251b17..833bbf8a885 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -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 modules = loadModuleScript(moduleFile); + public boolean compileModuleScript(String moduleFile, @Nullable String jarPath, @Nullable String outputDir, boolean jarRuntime) { + List 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 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; } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java index 641376b40b4..7a63ab18823 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java @@ -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 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 filesToAnalyzeCompletely = stubs ? Predicates.alwaysFalse() : Predicates.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 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(); diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/ErrorCollector.java b/compiler/cli/src/org/jetbrains/jet/compiler/MessageCollector.java similarity index 51% rename from compiler/cli/src/org/jetbrains/jet/compiler/ErrorCollector.java rename to compiler/cli/src/org/jetbrains/jet/compiler/MessageCollector.java index 8bf506a613b..397716a7c59 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/ErrorCollector.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/MessageCollector.java @@ -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 maps = LinkedHashMultimap.create(); +/*package*/ class MessageCollector { + // File path (nullable) -> error message + private final Multimap 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 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 diagnostics = groupedMessages.get(path); + for (String diagnostic : diagnostics) { + out.println(diagnostic); } } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/MessageRenderer.java b/compiler/cli/src/org/jetbrains/jet/compiler/MessageRenderer.java new file mode 100644 index 00000000000..4573f3d77eb --- /dev/null +++ b/compiler/cli/src/org/jetbrains/jet/compiler/MessageRenderer.java @@ -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("\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); +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 37c13801cc0..f5063500f7f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -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); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java index a06b0c9a3a0..1a1a6b655ad 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java @@ -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 diagnostic) { + @NotNull + public static LineAndColumn getLineAndColumn(@NotNull Diagnostic 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 + ")"; + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index aec915b4eff..bd0e8075768 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -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 = ""; + 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(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java index 7d95fd82c2d..3916d795dd1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -68,7 +68,7 @@ public class ImportsResolver { List importDirectives = file.getImportDirectives(); for (JetImportDirective importDirective : importDirectives) { Collection 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 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 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; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java index d1d2ec9d373..83fe600bc22 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java @@ -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 argumentExpressions) { + public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverDescriptor explicitReceiver, + @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, + @NotNull List argumentExpressions) { List arguments = Lists.newArrayList(); for (JetExpression argumentExpression : argumentExpressions) { arguments.add(makeValueArgument(argumentExpression, calleeExpression)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index aace789cd3f..3d2fccd1e3c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -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 task, @NotNull TracingStrategy tracing ) { OverloadResolutionResultsImpl 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 someFailed = EnumSet.of(OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES, OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH); + EnumSet 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 void replaceValueParametersWithSubstitutedOnes(ResolvedCallImpl candidateCall, @NotNull D substitutedDescriptor) { + private static void replaceValueParametersWithSubstitutedOnes( + ResolvedCallImpl candidateCall, @NotNull D substitutedDescriptor) { + Map parameterMap = Maps.newHashMap(); for (ValueParameterDescriptor valueParameterDescriptor : substitutedDescriptor.getValueParameters()) { parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor); @@ -726,7 +734,9 @@ public class CallResolver { return result; } - private ResolutionStatus checkReceiver(TracingStrategy tracing, ResolvedCallImpl candidateCall, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument, ResolutionTask task) { + private ResolutionStatus checkReceiver(TracingStrategy tracing, ResolvedCallImpl candidateCall, + ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument, + ResolutionTask 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> 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 failed = failedCandidates.iterator().next(); failed.getTrace().commit(); return OverloadResolutionResultsImpl.singleFailedCandidate(failed); @@ -861,7 +874,7 @@ public class CallResolver { } } - private boolean allClean(Collection> results) { + private static boolean allClean(Collection> results) { for (ResolvedCallImpl result : results) { if (result.isDirty()) return false; } @@ -939,7 +952,8 @@ public class CallResolver { return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.>emptySet()); } - private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, String name, List parameterTypes) { + private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, + String name, List parameterTypes) { List> result = Lists.newArrayList(); if (receiver.exists()) { Collection> extensionFunctionDescriptors = ResolvedCallImpl.convertCollection(scope.getFunctions(name)); @@ -966,7 +980,8 @@ public class CallResolver { } } - private boolean lookupExactSignature(Collection> candidates, List parameterTypes, List> result) { + private static boolean lookupExactSignature(Collection> candidates, List parameterTypes, + List> result) { boolean found = false; for (ResolvedCallImpl resolvedCall : candidates) { FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); @@ -979,7 +994,8 @@ public class CallResolver { return found; } - private boolean findExtensionFunctions(Collection> candidates, ReceiverDescriptor receiver, List parameterTypes, List> result) { + private boolean findExtensionFunctions(Collection> candidates, ReceiverDescriptor receiver, + List parameterTypes, List> result) { boolean found = false; for (ResolvedCallImpl resolvedCall : candidates) { FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); @@ -994,7 +1010,7 @@ public class CallResolver { return found; } - private boolean checkValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull List parameterTypes) { + private static boolean checkValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull List parameterTypes) { List valueParameters = functionDescriptor.getValueParameters(); if (valueParameters.size() != parameterTypes.size()) return false; for (int i = 0; i < valueParameters.size(); i++) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java index 6112c8e274a..17b50671f80 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java @@ -84,8 +84,8 @@ public class DelegatingCall implements Call { return delegate.getTypeArgumentList(); } + @NotNull @Override - @Nullable public PsiElement getCallElement() { return delegate.getCallElement(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java index 595c11f8a22..f16bacc72fa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java @@ -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; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java index cccbe65b914..333e6c40a2a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java @@ -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 { @@ -33,7 +35,7 @@ public enum ConstraintType implements Comparable { 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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java index d2ae4d7f0c1..e62052e741f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java @@ -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. diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 1cd5fe7bc1f..9fcaa801c48 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -347,7 +347,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { return null; } - private static OverloadResolutionResults resolveFakeCall(ExpressionReceiver receiver, ExpressionTypingContext context, String name) { + public static OverloadResolutionResults 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.emptyList()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index 8f80cc88cc2..1576399b249 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index 9e2ef4b0e3e..8d854b63269 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -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 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 declarationDescriptors = importResolver.processImportReference( + importDirective, scope, + new Importer.StandardImporter(writableScopeWithImports, false)); + + List callableExtensionDescriptors = new ArrayList(); + 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(); + } } diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java index 2cc50f58962..234b001ecfe 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java @@ -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(); + } + } } diff --git a/compiler/tests/compiler-tests.iml b/compiler/tests/compiler-tests.iml index e3a58fc3f6e..eee45ec38be 100644 --- a/compiler/tests/compiler-tests.iml +++ b/compiler/tests/compiler-tests.iml @@ -13,6 +13,7 @@ + diff --git a/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java b/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java index 422c9720536..12c982495df 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java @@ -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 javaFilesInDir(File dir) { diff --git a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java index c64bc07a62b..2336c3e013d 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java @@ -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"); } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JavaToJetCompletionResolver.java b/idea/src/org/jetbrains/jet/plugin/caches/JavaToJetCompletionResolver.java deleted file mode 100644 index de587c0abbb..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/caches/JavaToJetCompletionResolver.java +++ /dev/null @@ -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 getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) { - final ArrayList result = new ArrayList(); - - 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 getTopExtensionFunctionNames(TypeDescriptor typeDescriptor, Project project, - GlobalSearchScope scope) { - - return getPossiblePackageDeclarationsNames(project, scope); - } - -} diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java new file mode 100644 index 00000000000..50f95fb2150 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java @@ -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 getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) { + Collection result = new ArrayList(); + + 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 getTopExtensionFunctionNames(Project project, GlobalSearchScope scope) { + + // Extension function should have an parameter of type JetValueParameter with explicit receiver parameter. + + Set extensionNames = new HashSet(); + + Collection 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 getTopExtensionFunctionByName(String name, Project project, GlobalSearchScope scope) { + + Set selectedMethods = new HashSet(); + + Collection 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; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java index 1a1ce427549..7daa7a2db95 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java @@ -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 classNames = JetShortClassNameIndex.getInstance().getAllKeys(project); - return classNames.toArray(new String[classNames.size()]); + Collection 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 classNames = JetShortClassNameIndex.getInstance().getAllKeys(project); + Collection 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 getALlJetClassFQNames() { - final BindingContext context = getResolutionContext(GlobalSearchScope.allScope(project)); - return context.getKeys(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR); - } +// public Collection getALlJetClassFQNames() { +// final BindingContext context = getResolutionContext(GlobalSearchScope.allScope(project)); +// return context.getKeys(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR); +// } @NotNull public Collection 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() { @Override public boolean apply(@Nullable String fqName) { @@ -128,26 +128,24 @@ public class JetShortNamesCache extends PsiShortNamesCache { */ @NotNull public Collection getAllTopLevelFunctionNames() { - final HashSet functionNames = new HashSet(); + Set functionNames = new HashSet(); functionNames.addAll(JetShortFunctionNameIndex.getInstance().getAllKeys(project)); functionNames.addAll(JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, GlobalSearchScope.allScope(project))); return functionNames; } @NotNull - public Collection getTopLevelFunctionDescriptorsByName(final @NotNull String name, - final @NotNull GlobalSearchScope scope) { + public Collection getTopLevelFunctionDescriptorsByName(@NotNull String name, + @NotNull GlobalSearchScope scope) { - // TODO: Add jet function in jar-dependencies (those functions are missing in BindingContext and stubs) - - final Collection jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope); + Collection jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope); - final BindingContext context = getResolutionContext(scope); + BindingContext context = getResolutionContext(scope); - final HashSet result = new HashSet(); + HashSet result = new HashSet(); 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 getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) { + public Collection 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 getAllJetExtensionFunctionsNames(@NotNull GlobalSearchScope scope) { - final Set extensionFunctionNames = new HashSet(); + Set extensionFunctionNames = new HashSet(); extensionFunctionNames.addAll(JetExtensionFunctionNameIndex.getInstance().getAllKeys(project)); - extensionFunctionNames.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(null, project, scope)); + extensionFunctionNames.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(project, scope)); return extensionFunctionNames; } - public Collection 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 getJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) { + HashSet functions = new HashSet(); + functions.addAll(JetExtensionFunctionNameIndex.getInstance().get(name, project, scope)); + functions.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionByName(name, project, scope)); - final Collection jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope); + return functions; + } - final BindingContext context = getResolutionContext(scope); + public Collection getJetFunctionsByName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope) { + return JetShortFunctionNameIndex.getInstance().get(name, project, scope); + } - final HashSet result = new HashSet(); - - 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 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 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 diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java index bd42098adec..04c0a6bebe7 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java @@ -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 categories = new HashMap(); - 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("(.*?)", 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); + } + } + } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index a7b90559619..e0417995695 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -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() { @Override protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, - final @NotNull CompletionResultSet result) { + @NotNull CompletionResultSet result) { - final HashSet positions = new HashSet(); + Set positions = new HashSet(); 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 extensionFunctionsNames = namesCache.getAllJetExtensionFunctionsNames( + GlobalSearchScope.allScope(position.getProject())); + + Set functionFQNs = new HashSet(); + + // Collect all possible extension function qualified names + for (String name : extensionFunctionsNames) { + if (result.getPrefixMatcher().prefixMatches(name)) { + Collection 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 positions) { + @NotNull Set 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 positions) { + @NotNull Set 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 functionNames = namesCache.getAllTopLevelFunctionNames(); + JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache(); + GlobalSearchScope scope = GlobalSearchScope.allScope(project); + Collection 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 positions) { + @NotNull final Set positions) { JetClassCompletionContributor.addClasses(parameters, result, new Consumer() { @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 positions) { + @NotNull Set 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. + } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java index 75f3c44fbd1..b62ddcd5fef 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java @@ -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 { diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java index 40612db4ebd..9e46c7c00d4 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java @@ -115,11 +115,6 @@ public class JetFunctionInsertHandler implements InsertHandler { 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 { 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 diff --git a/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java index 9b843f235f7..e7388dcc7d1 100644 --- a/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java @@ -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 templates = listApplicableTemplates(file, offset); diff --git a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetSuggestVariableNameMacro.java b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetSuggestVariableNameMacro.java index 2bb9ebdcd17..1e0183f1776 100644 --- a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetSuggestVariableNameMacro.java +++ b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetSuggestVariableNameMacro.java @@ -30,7 +30,7 @@ import org.jetbrains.jet.plugin.JetBundle; public class JetSuggestVariableNameMacro extends Macro { @Override public String getName() { - return "suggestVariableName"; + return "kotlinSuggestVariableName"; } @Override diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java b/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java index 97572a1652e..923efa85391 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java @@ -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); - } } } } diff --git a/idea/testData/completion/basic/ExtensionFromStandardLibrary.kt b/idea/testData/completion/basic/ExtensionFromStandardLibrary.kt new file mode 100644 index 00000000000..f662efd8701 --- /dev/null +++ b/idea/testData/completion/basic/ExtensionFromStandardLibrary.kt @@ -0,0 +1,13 @@ +package first + +import java.util.ArrayList + +fun firstFun() { + val a = ArrayList() + a.toLinke +} + +// RUNTIME: 1 +// TIME: 2 +// EXIST: toLinkedList +// NUMBER: 1 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/DoNotCompleteWithConstraints-1.kt b/idea/testData/completion/basic/multifile/DoNotCompleteWithConstraints-1.kt new file mode 100644 index 00000000000..2bc456b90ab --- /dev/null +++ b/idea/testData/completion/basic/multifile/DoNotCompleteWithConstraints-1.kt @@ -0,0 +1,15 @@ +package first + +trait TestedTrait() { +} + +fun firstFun() { + val a = second.SomeTest() + a.testing +} + +// EXIST: testingMethod +// EXIST: testingExpectedFunction +// ABSENT: testingUnexpectedFunction + +// NUMBER: 2 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/DoNotCompleteWithConstraints-2.kt b/idea/testData/completion/basic/multifile/DoNotCompleteWithConstraints-2.kt new file mode 100644 index 00000000000..4614b598b5e --- /dev/null +++ b/idea/testData/completion/basic/multifile/DoNotCompleteWithConstraints-2.kt @@ -0,0 +1,16 @@ +package second + +open class SomeOther() {} + +class SomeTest { + fun testingMethod() { + + } +} + +fun SomeTest.testingUnexpectedFunction() { +} + +fun SomeTest.testingExpectedFunction(i : Int) : String { + return "" +} \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/ExtensionFunctionOnUnresolved-1.kt b/idea/testData/completion/basic/multifile/ExtensionFunctionOnUnresolved-1.kt new file mode 100644 index 00000000000..784ac599a7a --- /dev/null +++ b/idea/testData/completion/basic/multifile/ExtensionFunctionOnUnresolved-1.kt @@ -0,0 +1,11 @@ +package first + +fun firstFun() { + val a = SomeUnknownClass() + a.hello +} + +// ABSENT: helloFun +// ABSENT: helloFunPreventAutoInsert +// ABSENT: helloWithParams +// NUMBER: 0 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/ExtensionFunctionOnUnresolved-2.kt b/idea/testData/completion/basic/multifile/ExtensionFunctionOnUnresolved-2.kt new file mode 100644 index 00000000000..26ba80640b4 --- /dev/null +++ b/idea/testData/completion/basic/multifile/ExtensionFunctionOnUnresolved-2.kt @@ -0,0 +1,11 @@ +package second + +fun String.helloFun() { +} + +fun String.helloWithParams(i : Int) : String { + return "" +} + +fun String.helloFunPreventAutoInsert() { +} \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/ExtensionOnNullable-1.kt b/idea/testData/completion/basic/multifile/ExtensionOnNullable-1.kt new file mode 100644 index 00000000000..66e065edf74 --- /dev/null +++ b/idea/testData/completion/basic/multifile/ExtensionOnNullable-1.kt @@ -0,0 +1,12 @@ +package first + +fun firstFun() { + val a : String? = "" + a.hello +} + +// EXIST: helloFun +// EXIST: helloFunPreventAutoInsert +// EXIST: helloWithParams +// ABSENT: helloFake +// NUMBER: 3 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/ExtensionOnNullable-2.kt b/idea/testData/completion/basic/multifile/ExtensionOnNullable-2.kt new file mode 100644 index 00000000000..0d782748e87 --- /dev/null +++ b/idea/testData/completion/basic/multifile/ExtensionOnNullable-2.kt @@ -0,0 +1,14 @@ +package second + +fun String.helloFun() { +} + +fun String.helloWithParams(i : Int) : String { + return "" +} + +fun String.helloFunPreventAutoInsert() { +} + +fun Int.helloFake() { +} \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/ExtensionProperty-1.kt b/idea/testData/completion/basic/multifile/ExtensionProperty-1.kt new file mode 100644 index 00000000000..45b5e8b4acc --- /dev/null +++ b/idea/testData/completion/basic/multifile/ExtensionProperty-1.kt @@ -0,0 +1,12 @@ +package first + +import second.SomeTestClass + +fun firstFun() { + SomeTestClass().some +} + +// EXIST: someProperty +// EXIST: someOtherProperty +// EXIST: someSelfProperty +// NUMBER: 3 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/ExtensionProperty-2.kt b/idea/testData/completion/basic/multifile/ExtensionProperty-2.kt new file mode 100644 index 00000000000..a8e890a7fa3 --- /dev/null +++ b/idea/testData/completion/basic/multifile/ExtensionProperty-2.kt @@ -0,0 +1,8 @@ +package second + +class SomeTestClass() { +} + +val SomeTestClass.someProperty = 12 +var SomeTestClass.someOtherProperty = "" +val SomeTestClass.someSelfProperty = SomeTestClass() \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-1.kt b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-1.kt new file mode 100644 index 00000000000..dda68250d5e --- /dev/null +++ b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-1.kt @@ -0,0 +1,12 @@ +package first + +fun firstFun() { + val a = "" + a.hello +} + +// EXIST: helloFun +// EXIST: helloFunPreventAutoInsert +// EXIST: helloWithParams +// ABSENT: helloFake +// NUMBER: 3 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-2.kt b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-2.kt new file mode 100644 index 00000000000..0d782748e87 --- /dev/null +++ b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-2.kt @@ -0,0 +1,14 @@ +package second + +fun String.helloFun() { +} + +fun String.helloWithParams(i : Int) : String { + return "" +} + +fun String.helloFunPreventAutoInsert() { +} + +fun Int.helloFake() { +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/ExtensionFunctions-1.kt b/idea/testData/completion/handlers/multifile/ExtensionFunctions-1.kt new file mode 100644 index 00000000000..9b743c13c61 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/ExtensionFunctions-1.kt @@ -0,0 +1,6 @@ +package first + +fun firstFun() { + val a = "" + a.hello +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/ExtensionFunctions-2.kt b/idea/testData/completion/handlers/multifile/ExtensionFunctions-2.kt new file mode 100644 index 00000000000..2f98c0a94f4 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/ExtensionFunctions-2.kt @@ -0,0 +1,4 @@ +package second + +fun String.helloFun() { +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/ExtensionFunctions.kt.after b/idea/testData/completion/handlers/multifile/ExtensionFunctions.kt.after new file mode 100644 index 00000000000..d2679999b61 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/ExtensionFunctions.kt.after @@ -0,0 +1,8 @@ +package first + +import second.helloFun + +fun firstFun() { + val a = "" + a.helloFun() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java b/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java index 2ec8535261a..5b0b9b10783 100644 --- a/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java +++ b/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java @@ -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]); } diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java index 660e9d1f92f..24927696af2 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -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() + diff --git a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java index 4c832c5cee6..a9218f58514 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java +++ b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java @@ -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); diff --git a/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java index 66c76b9d1cf..7056bf1131c 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java @@ -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(); diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java index 68e78e1c80e..e6311d8e58a 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java @@ -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(); } diff --git a/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java b/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java index a698d4fea2b..e666476b25f 100644 --- a/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java +++ b/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java @@ -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; + } + } + } + } } diff --git a/js/js.tests/js.tests.iml b/js/js.tests/js.tests.iml index 72acf26a5cc..aa9f0a6aab3 100644 --- a/js/js.tests/js.tests.iml +++ b/js/js.tests/js.tests.iml @@ -5,7 +5,7 @@ - + diff --git a/js/js.tests/test/org/jetbrains/k2js/test/ArrayListTest.java b/js/js.tests/test/org/jetbrains/k2js/test/ArrayListTest.java index 7e3f7506cab..85d4a4706cc 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/ArrayListTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/ArrayListTest.java @@ -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) { diff --git a/js/js.tests/test/org/jetbrains/k2js/test/ClassInheritanceTest.java b/js/js.tests/test/org/jetbrains/k2js/test/ClassInheritanceTest.java index ed2d3369c68..6aa1d44b8cc 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/ClassInheritanceTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/ClassInheritanceTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/ConditionalTest.java b/js/js.tests/test/org/jetbrains/k2js/test/ConditionalTest.java index 8eaec5f933c..01bc150435f 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/ConditionalTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/ConditionalTest.java @@ -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) { diff --git a/js/js.tests/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java b/js/js.tests/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java index 783d67f71ec..428fdad5ed7 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/ExtensionPropertyTest.java b/js/js.tests/test/org/jetbrains/k2js/test/ExtensionPropertyTest.java index 983dd8ab86f..c6387d097bb 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/ExtensionPropertyTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/ExtensionPropertyTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/ForTest.java b/js/js.tests/test/org/jetbrains/k2js/test/ForTest.java index 6c469fc070e..4ea77af1c5d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/ForTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/ForTest.java @@ -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"); } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/k2js/test/FunctionTest.java b/js/js.tests/test/org/jetbrains/k2js/test/FunctionTest.java index c339e7343af..f819c841a4d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/FunctionTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/FunctionTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/KotlinLibTest.java b/js/js.tests/test/org/jetbrains/k2js/test/KotlinLibTest.java index ea94e687ba9..2fb1afd4e19 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/KotlinLibTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/KotlinLibTest.java @@ -55,7 +55,7 @@ public final class KotlinLibTest extends TranslationTest { final Map> propertyToType = new HashMap>(); 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> propertyToType = new HashMap>(); 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; } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/MiscTest.java b/js/js.tests/test/org/jetbrains/k2js/test/MiscTest.java index d56a8371b78..b34076ddce0 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/MiscTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/MiscTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/MultiFileTest.java b/js/js.tests/test/org/jetbrains/k2js/test/MultiFileTest.java index 76738d49285..4b0a375f952 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/MultiFileTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/MultiFileTest.java @@ -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); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/MultiNamespaceTest.java b/js/js.tests/test/org/jetbrains/k2js/test/MultiNamespaceTest.java index 8d7d473d636..cdc9b928b36 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/MultiNamespaceTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/MultiNamespaceTest.java @@ -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); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/NameClashesTest.java b/js/js.tests/test/org/jetbrains/k2js/test/NameClashesTest.java index 67f563d2430..c3c7d2c5bc8 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/NameClashesTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/NameClashesTest.java @@ -29,6 +29,6 @@ public final class NameClashesTest extends TranslationTest { } public void testMethodOverload() throws Exception { - testFooBoxIsTrue("methodOverload.kt"); + checkFooBoxIsTrue("methodOverload.kt"); } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/k2js/test/ObjectTest.java b/js/js.tests/test/org/jetbrains/k2js/test/ObjectTest.java index f0824057fdc..c40cebca8fa 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/ObjectTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/ObjectTest.java @@ -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"); } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java b/js/js.tests/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java index d36e34ed211..61a0fe93124 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/PatternMatchingTest.java b/js/js.tests/test/org/jetbrains/k2js/test/PatternMatchingTest.java index d9ff84c1b0e..7bb03d3fd06 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/PatternMatchingTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/PatternMatchingTest.java @@ -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) { } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/PropertyAccessTest.java b/js/js.tests/test/org/jetbrains/k2js/test/PropertyAccessTest.java index d08b4b1dd52..78d7e0243dc 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/PropertyAccessTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/PropertyAccessTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/RTTITest.java b/js/js.tests/test/org/jetbrains/k2js/test/RTTITest.java index 03ea3e85b9c..2529fbcc5ee 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/RTTITest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/RTTITest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/RangeTest.java b/js/js.tests/test/org/jetbrains/k2js/test/RangeTest.java index fe3b89d2756..6fbc5269a41 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/RangeTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/RangeTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/SimpleTestSuite.java b/js/js.tests/test/org/jetbrains/k2js/test/SimpleTestSuite.java index 6f8f741ca4f..5b7637a36ba 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/SimpleTestSuite.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/SimpleTestSuite.java @@ -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); } }); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/StandardClassesTest.java b/js/js.tests/test/org/jetbrains/k2js/test/StandardClassesTest.java index 95b2cbedcf1..51578051cc4 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/StandardClassesTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/StandardClassesTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/StringTest.java b/js/js.tests/test/org/jetbrains/k2js/test/StringTest.java index bf45441f9e7..b01412c5f06 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/StringTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/StringTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/Suite.java b/js/js.tests/test/org/jetbrains/k2js/test/Suite.java index 75ff01988a0..4151de967e5 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/Suite.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/Suite.java @@ -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 { diff --git a/js/js.tests/test/org/jetbrains/k2js/test/TraitTest.java b/js/js.tests/test/org/jetbrains/k2js/test/TraitTest.java index f58d18d038f..0363121db1c 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/TraitTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/TraitTest.java @@ -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"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/TranslationTest.java b/js/js.tests/test/org/jetbrains/k2js/test/TranslationTest.java index bbb77c11318..dcb12157e3d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/TranslationTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/TranslationTest.java @@ -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 fullFilePaths = new ArrayList(); 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 fileNames, RhinoResultChecker checker) throws Exception { + protected static void runRhinoTest(@NotNull List 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(); } } - - } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/TranslatorTestCaseBuilder.java b/js/js.tests/test/org/jetbrains/k2js/test/TranslatorTestCaseBuilder.java index ff9a8ed4c78..4f6b8c7cdb2 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/TranslatorTestCaseBuilder.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/TranslatorTestCaseBuilder.java @@ -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); diff --git a/js/js.tests/test/org/jetbrains/k2js/test/TupleTest.java b/js/js.tests/test/org/jetbrains/k2js/test/TupleTest.java index d40b350d90f..e2e18fbe6e8 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/TupleTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/TupleTest.java @@ -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"); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java b/js/js.tests/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java index 1eb409c2b8a..cd9da6a45b3 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java @@ -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", ""); // } } diff --git a/js/js.translator/lib/args4j-2.0.12.jar b/js/js.translator/lib/args4j-2.0.12.jar new file mode 100644 index 00000000000..61a4d5a6485 Binary files /dev/null and b/js/js.translator/lib/args4j-2.0.12.jar differ diff --git a/js/js.translator/lib/dartc.jar b/js/js.translator/lib/dartc.jar index 5ffa521701b..c0e03cf6411 100644 Binary files a/js/js.translator/lib/dartc.jar and b/js/js.translator/lib/dartc.jar differ diff --git a/js/js.translator/lib/guava-10.0.1.jar b/js/js.translator/lib/guava-10.0.1.jar deleted file mode 100644 index d107c0f3b0c..00000000000 Binary files a/js/js.translator/lib/guava-10.0.1.jar and /dev/null differ diff --git a/js/js.translator/lib/json.jar b/js/js.translator/lib/json.jar new file mode 100644 index 00000000000..b8838d19dc7 Binary files /dev/null and b/js/js.translator/lib/json.jar differ diff --git a/js/js.translator/src/org/jetbrains/k2js/analyze/Analyzer.java b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacade.java similarity index 92% rename from js/js.translator/src/org/jetbrains/k2js/analyze/Analyzer.java rename to js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacade.java index 9337a34131a..890f0624499 100644 --- a/js/js.translator/src/org/jetbrains/k2js/analyze/Analyzer.java +++ b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacade.java @@ -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 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 { diff --git a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java index fe744752b94..7840ead283d 100644 --- a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java @@ -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 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 parseString(@NotNull String argumentString) { + private static List parseString(@NotNull String argumentString) { List result = new ArrayList(); StringTokenizer stringTokenizer = new StringTokenizer(argumentString); while (stringTokenizer.hasMoreTokens()) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/NamingScope.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/NamingScope.java index 6b267859ab2..122bad33a81 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/NamingScope.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/NamingScope.java @@ -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 nameIterator = scope.getAllNames(); - while (nameIterator.hasNext()) { - if (nameIterator.next() == name) { - return true; - } - } - return false; - } - @NotNull public JsName declareTemporary() { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java index b588c225ecc..bb3de688359 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java @@ -323,6 +323,7 @@ public final class StaticContext { } } + @NotNull private NamingScope getEnclosingScope(@NotNull DeclarationDescriptor descriptor) { DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor); return getScopeForDescriptor(containingDeclaration.getOriginal()); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java index 35c86f5dc6d..75c2071bbe6 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java @@ -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 diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java index 4309096dd25..cbff606f420 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java @@ -100,7 +100,7 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { } @NotNull - private List declarationStatements(@NotNull List namespaceTranslators) { + private static List declarationStatements(@NotNull List namespaceTranslators) { List result = Lists.newArrayList(); for (NamespaceTranslator translator : namespaceTranslators) { result.add(translator.getDeclarationStatement()); @@ -109,7 +109,7 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { } @NotNull - private List initializeStatements(@NotNull List namespaceTranslators) { + private static List initializeStatements(@NotNull List namespaceTranslators) { List result = Lists.newArrayList(); for (NamespaceTranslator translator : namespaceTranslators) { result.add(translator.getInitializeStatement()); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java index f026b6aed24..6f7380e1040 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java @@ -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 propertyList = new ArrayList(); 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); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 23770651790..fa6c0c2c373 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -224,6 +224,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { 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) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java index 6441f04b066..eeca826c737 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java @@ -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() { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java index 58c1a09d8bb..73401186594 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java @@ -28,7 +28,6 @@ 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.BindingUtils; -import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils; import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; @@ -134,6 +133,6 @@ public final class PatternTranslator extends AbstractTranslator { assert patternExpression != null : "Expression patter should have an expression."; JsExpression expressionToMatchAgainst = Translation.translateAsExpression(patternExpression, context()); - return JsAstUtils.equals(expressionToMatch, expressionToMatchAgainst); + return equality(expressionToMatch, expressionToMatchAgainst); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java index 42432d4bba9..d33d534b17e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java @@ -82,8 +82,8 @@ public class WhenTranslator extends AbstractTranslator { @NotNull private JsStatement surroundWithDummyIf(@NotNull JsStatement entryStatement) { - JsExpression stepNumberEqualsCurrentEntryNumber = new JsBinaryOperation(JsBinaryOperator.EQ, - dummyCounter.reference(), program().getNumberLiteral(currentEntryNumber)); + JsNumberLiteral jsEntryNumber = program().getNumberLiteral(this.currentEntryNumber); + JsExpression stepNumberEqualsCurrentEntryNumber = equality(dummyCounter.reference(), jsEntryNumber); currentEntryNumber++; return new JsIf(stepNumberEqualsCurrentEntryNumber, entryStatement, null); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ArrayForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ArrayForTranslator.java index ecd94aac82a..fa2d508388b 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ArrayForTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ArrayForTranslator.java @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.Translation; -import org.jetbrains.k2js.translate.intrinsic.string.LengthIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import org.jetbrains.k2js.translate.utils.BindingUtils; import java.util.Collections; @@ -34,7 +34,6 @@ import java.util.List; import static org.jetbrains.k2js.translate.expression.foreach.ForTranslatorUtils.temporariesInitialization; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getClassDescriptorForType; import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; -import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody; import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange; /** @@ -43,8 +42,8 @@ import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange; public final class ArrayForTranslator extends ForTranslator { @NotNull - public static JsStatement translate(@NotNull JetForExpression expression, - @NotNull TranslationContext context) { + public static JsStatement doTranslate(@NotNull JetForExpression expression, + @NotNull TranslationContext context) { return (new ArrayForTranslator(expression, context).translate()); } @@ -70,7 +69,10 @@ public final class ArrayForTranslator extends ForTranslator { private ArrayForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) { super(forExpression, context); loopRange = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context)); - JsExpression length = LengthIntrinsic.INSTANCE.apply(loopRange.reference(), Collections.emptyList(), context()); + Intrinsic lengthPropertyIntrinsic = context().intrinsics().getLengthPropertyIntrinsic(); + JsExpression length = lengthPropertyIntrinsic.apply(loopRange.reference(), + Collections.emptyList(), + context()); end = context().declareTemporary(length); index = context().declareTemporary(program().getNumberLiteral(0)); } @@ -78,36 +80,27 @@ public final class ArrayForTranslator extends ForTranslator { @NotNull private JsBlock translate() { List blockStatements = temporariesInitialization(loopRange, end); - blockStatements.add(generateForExpression()); + blockStatements.add(generateForExpression(getInitExpression(), getCondition(), getIncrExpression(), getBody())); return newBlock(blockStatements); } - @NotNull - private JsFor generateForExpression() { - JsFor result = new JsFor(); - result.setInitVars(initExpression()); - result.setCondition(getCondition()); - result.setIncrExpr(getIncrExpression()); - result.setBody(getBody()); - return result; - } @NotNull private JsStatement getBody() { JsArrayAccess arrayAccess = new JsArrayAccess(loopRange.reference(), index.reference()); JsStatement currentVar = newVar(parameterName, arrayAccess); - JsStatement realBody = Translation.translateAsStatement(getLoopBody(expression), context()); + JsStatement realBody = translateOriginalBodyExpression(); return AstUtil.newBlock(currentVar, realBody); } @NotNull - private JsVars initExpression() { + private JsVars getInitExpression() { return newVar(index.name(), program().getNumberLiteral(0)); } @NotNull private JsExpression getCondition() { - return notEqual(index.reference(), end.reference()); + return inequality(index.reference(), end.reference()); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ForTranslator.java index 776d8d578e8..831769a86d1 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ForTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/ForTranslator.java @@ -39,15 +39,15 @@ public abstract class ForTranslator extends AbstractTranslator { public static JsStatement translate(@NotNull JetForExpression expression, @NotNull TranslationContext context) { if (RangeLiteralForTranslator.isApplicable(expression, context)) { - return RangeLiteralForTranslator.translate(expression, context); + return RangeLiteralForTranslator.doTranslate(expression, context); } if (RangeForTranslator.isApplicable(expression, context)) { - return RangeForTranslator.translate(expression, context); + return RangeForTranslator.doTranslate(expression, context); } if (ArrayForTranslator.isApplicable(expression, context)) { - return ArrayForTranslator.translate(expression, context); + return ArrayForTranslator.doTranslate(expression, context); } - return IteratorForTranslator.translate(expression, context); + return IteratorForTranslator.doTranslate(expression, context); } @NotNull @@ -67,7 +67,6 @@ public abstract class ForTranslator extends AbstractTranslator { return context().getNameForElement(loopParameter); } - //TODO: look for should-be-usages @NotNull protected JsStatement translateOriginalBodyExpression() { return Translation.translateAsStatement(getLoopBody(expression), context()); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java index 8b537937218..b088e0114f7 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java @@ -41,8 +41,8 @@ import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange; public final class IteratorForTranslator extends ForTranslator { @NotNull - public static JsStatement translate(@NotNull JetForExpression expression, - @NotNull TranslationContext context) { + public static JsStatement doTranslate(@NotNull JetForExpression expression, + @NotNull TranslationContext context) { return (new IteratorForTranslator(expression, context).translate()); } @@ -61,6 +61,7 @@ public final class IteratorForTranslator extends ForTranslator { return AstUtil.newBlock(iterator.assignmentExpression().makeStmt(), cycle); } + //TODO: check whether complex logic with blocks is needed @NotNull private JsBlock generateCycleBody() { JsBlock cycleBody = new JsBlock(); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java index e8501e036ee..c509b2fb80a 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java @@ -32,7 +32,6 @@ import java.util.List; import static org.jetbrains.k2js.translate.expression.foreach.ForTranslatorUtils.temporariesInitialization; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getClassDescriptorForType; import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; -import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody; import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange; /** @@ -42,8 +41,8 @@ public final class RangeForTranslator extends ForTranslator { //TODO: inspection @NotNull - public static JsStatement translate(@NotNull JetForExpression expression, - @NotNull TranslationContext context) { + public static JsStatement doTranslate(@NotNull JetForExpression expression, + @NotNull TranslationContext context) { return (new RangeForTranslator(expression, context).translate()); } @@ -52,6 +51,7 @@ public final class RangeForTranslator extends ForTranslator { JetExpression loopRange = getLoopRange(expression); JetType rangeType = BindingUtils.getTypeForExpression(context.bindingContext(), loopRange); //TODO: better check + //TODO: long range? return getClassDescriptorForType(rangeType).getName().equals("IntRange"); } @@ -73,7 +73,7 @@ public final class RangeForTranslator extends ForTranslator { program().getNumberLiteral(1)); incrVar = context().declareTemporary(incrVarValue); start = context().declareTemporary(callFunction("get_start")); - end = context().declareTemporary(new JsBinaryOperation(JsBinaryOperator.ADD, callFunction("get_end"), incrVar.reference())); + end = context().declareTemporary(sum(callFunction("get_end"), incrVar.reference())); } @NotNull @@ -89,7 +89,7 @@ public final class RangeForTranslator extends ForTranslator { result.setInitVars(initExpression()); result.setCondition(getCondition()); result.setIncrExpr(getIncrExpression()); - result.setBody(Translation.translateAsStatement(getLoopBody(expression), context())); + result.setBody(translateOriginalBodyExpression()); return result; } @@ -100,12 +100,12 @@ public final class RangeForTranslator extends ForTranslator { @NotNull private JsExpression getCondition() { - return notEqual(parameterName.makeRef(), end.reference()); + return inequality(parameterName.makeRef(), end.reference()); } @NotNull private JsExpression getIncrExpression() { - return new JsBinaryOperation(JsBinaryOperator.ASG_ADD, parameterName.makeRef(), incrVar.reference()); + return addAssign(parameterName.makeRef(), incrVar.reference()); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeLiteralForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeLiteralForTranslator.java index 585c98e9807..2f4baa5c046 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeLiteralForTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeLiteralForTranslator.java @@ -41,8 +41,8 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRight public final class RangeLiteralForTranslator extends ForTranslator { @NotNull - public static JsStatement translate(@NotNull JetForExpression expression, - @NotNull TranslationContext context) { + public static JsStatement doTranslate(@NotNull JetForExpression expression, + @NotNull TranslationContext context) { return (new RangeLiteralForTranslator(expression, context).translate()); } @@ -80,20 +80,13 @@ public final class RangeLiteralForTranslator extends ForTranslator { @NotNull private JsBlock translate() { List blockStatements = temporariesInitialization(rangeEnd); - blockStatements.add(generateForExpression()); + blockStatements.add(generateForExpression(initExpression(), + getCondition(), + getIncrExpression(), + translateOriginalBodyExpression())); return newBlock(blockStatements); } - @NotNull - private JsFor generateForExpression() { - JsFor result = new JsFor(); - result.setInitVars(initExpression()); - result.setCondition(getCondition()); - result.setIncrExpr(getIncrExpression()); - result.setBody(translateOriginalBodyExpression()); - return result; - } - @NotNull private JsVars initExpression() { return newVar(parameterName, rangeStart); @@ -101,7 +94,7 @@ public final class RangeLiteralForTranslator extends ForTranslator { @NotNull private JsExpression getCondition() { - return notEqual(parameterName.makeRef(), rangeEnd.reference()); + return inequality(parameterName.makeRef(), rangeEnd.reference()); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java index 2f6e99bbe9b..44ba8651e96 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java @@ -48,8 +48,9 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla private final List initializerStatements = new ArrayList(); public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { - super(context.getScopeForElement(classDeclaration).innerScope - ("initializer " + classDeclaration.getName()), context); + // Note: it's important we use scope for class descriptor because anonymous function used in property initializers + // belong to the properties themselves + super(context.getScopeForDescriptor(getClassDescriptor(context.bindingContext(), classDeclaration)), context); this.classDeclaration = classDeclaration; } @@ -83,6 +84,7 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla private void addCallToSuperMethod(@NotNull JetDelegatorToSuperCall superCall) { //TODO: look into JsName superMethodName = initializerMethodScope.jsScope().declareName(Namer.superMethodName()); + superMethodName.setObfuscatable(false); List arguments = translateArguments(superCall); initializerStatements.add(convertToStatement(newInvocation(thisQualifiedReference(superMethodName), arguments))); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java index 3e7173779c0..b0732d319f2 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java @@ -32,8 +32,8 @@ public final class NamespaceInitializerTranslator extends AbstractInitializerTra private final NamespaceDescriptor namespace; public NamespaceInitializerTranslator(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) { - super(context.getScopeForDescriptor(namespace).innerScope - ("initializer " + namespace.getName()), context); + //NOTE: + super(context.getScopeForDescriptor(namespace), context); this.namespace = namespace; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/FunctionIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/FunctionIntrinsic.java deleted file mode 100644 index 9a5e0eab723..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/FunctionIntrinsic.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.k2js.translate.intrinsic; - -/** - * @author Pavel Talanov - */ -public interface FunctionIntrinsic extends Intrinsic { - -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java index 9893e8f489d..8a130b98c71 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java @@ -26,10 +26,12 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.PrimitiveType; import org.jetbrains.jet.lexer.JetToken; -import org.jetbrains.k2js.translate.intrinsic.array.*; +import org.jetbrains.k2js.translate.intrinsic.array.ArrayGetIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.array.ArraySetIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.array.BuiltInPropertyIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.array.CallStandardMethodIntrinsic; import org.jetbrains.k2js.translate.intrinsic.primitive.*; import org.jetbrains.k2js.translate.intrinsic.string.CharAtIntrinsic; -import org.jetbrains.k2js.translate.intrinsic.string.LengthIntrinsic; import org.jetbrains.k2js.translate.intrinsic.tuple.TupleAccessIntrinsic; import org.jetbrains.k2js.translate.operation.OperatorTable; import org.jetbrains.k2js.translate.utils.DescriptorUtils; @@ -50,8 +52,8 @@ import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getPropertyByNa public final class Intrinsics { @NotNull - private final Map functionIntrinsics = - new HashMap(); + private final Map functionIntrinsics = + new HashMap(); @NotNull private final Map equalsIntrinsics = @@ -61,6 +63,9 @@ public final class Intrinsics { private final Map compareToIntrinsics = new HashMap(); + @NotNull + private final Intrinsic lengthPropertyIntrinsic = new BuiltInPropertyIntrinsic("length"); + public static Intrinsics standardLibraryIntrinsics(@NotNull JetStandardLibrary library) { return new Intrinsics(library); } @@ -76,6 +81,11 @@ public final class Intrinsics { declareArrayIntrinsics(); } + @NotNull + public Intrinsic getLengthPropertyIntrinsic() { + return lengthPropertyIntrinsic; + } + private void declareTuplesIntrinsics() { for (int tupleSize = 0; tupleSize < JetStandardClasses.TUPLE_COUNT; ++tupleSize) { declareTupleIntrinsics(tupleSize); @@ -94,9 +104,8 @@ public final class Intrinsics { } private void declareNullConstructorIntrinsic() { - //TODO: FunctionDescriptor nullArrayConstructor = library.getLibraryScope().getFunctions("Array").iterator().next(); - functionIntrinsics.put(nullArrayConstructor, ArrayNullConstructorIntrinsic.INSTANCE); + functionIntrinsics.put(nullArrayConstructor, new CallStandardMethodIntrinsic("Kotlin.nullArray", false, 1)); } //TODO: some dangerous operation unchecked here @@ -107,14 +116,15 @@ public final class Intrinsics { FunctionDescriptor getFunction = getFunctionByName(arrayMemberScope, "get"); functionIntrinsics.put(getFunction, ArrayGetIntrinsic.INSTANCE); PropertyDescriptor sizeProperty = getPropertyByName(arrayMemberScope, "size"); - functionIntrinsics.put(sizeProperty.getGetter(), ArraySizeIntrinsic.INSTANCE); + functionIntrinsics.put(sizeProperty.getGetter(), lengthPropertyIntrinsic); + //TODO: excessive object creation PropertyDescriptor indicesProperty = getPropertyByName(arrayMemberScope, "indices"); - functionIntrinsics.put(indicesProperty.getGetter(), ArrayIndicesIntrinsic.INSTANCE); + functionIntrinsics.put(indicesProperty.getGetter(), new CallStandardMethodIntrinsic("Kotlin.arrayIndices", true, 0)); FunctionDescriptor iteratorFunction = getFunctionByName(arrayMemberScope, "iterator"); - functionIntrinsics.put(iteratorFunction, ArrayIteratorIntrinsic.INSTANCE); + functionIntrinsics.put(iteratorFunction, new CallStandardMethodIntrinsic("Kotlin.arrayIterator", true, 0)); ConstructorDescriptor arrayConstructor = ((ClassDescriptor) arrayMemberScope.getContainingDeclaration()).getConstructors().iterator().next(); - functionIntrinsics.put(arrayConstructor, ArrayFunctionConstructorIntrinsic.INSTANCE); + functionIntrinsics.put(arrayConstructor, new CallStandardMethodIntrinsic("Kotlin.arrayFromFun", false, 2)); } private List getLibraryArrayTypes() { @@ -137,7 +147,7 @@ public final class Intrinsics { private void declareStringIntrinsics() { PropertyDescriptor lengthProperty = getPropertyByName(library.getCharSequence().getDefaultType().getMemberScope(), "length"); - functionIntrinsics.put(lengthProperty.getGetter(), LengthIntrinsic.INSTANCE); + functionIntrinsics.put(lengthProperty.getGetter(), new BuiltInPropertyIntrinsic("length")); FunctionDescriptor getFunction = getFunctionByName(library.getString().getDefaultType().getMemberScope(), "get"); functionIntrinsics.put(getFunction, CharAtIntrinsic.INSTANCE); @@ -173,7 +183,7 @@ public final class Intrinsics { } @NotNull - public FunctionIntrinsic getFunctionIntrinsic(@NotNull FunctionDescriptor descriptor) { + public Intrinsic getFunctionIntrinsic(@NotNull FunctionDescriptor descriptor) { return functionIntrinsics.get(descriptor.getOriginal()); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayGetIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayGetIntrinsic.java index ea0d565247d..c786cc6fc09 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayGetIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayGetIntrinsic.java @@ -21,14 +21,14 @@ import com.google.dart.compiler.backend.js.ast.JsExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.List; /** * @author Pavel Talanov */ -public enum ArrayGetIntrinsic implements FunctionIntrinsic { +public enum ArrayGetIntrinsic implements Intrinsic { INSTANCE; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayIndicesIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayIndicesIntrinsic.java deleted file mode 100644 index c9e9f9d1005..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayIndicesIntrinsic.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.k2js.translate.intrinsic.array; - -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.util.AstUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; - -import java.util.List; - -/** - * @author Pavel Talanov - */ -public enum ArrayIndicesIntrinsic implements FunctionIntrinsic { - - INSTANCE; - - - @NotNull - @Override - public JsExpression apply(@Nullable JsExpression receiver, @NotNull List arguments, - @NotNull TranslationContext context) { - assert receiver != null; - assert arguments.size() == 0; - //TODO: provide better mechanism - JsNameRef iteratorFunName = AstUtil.newQualifiedNameRef("Kotlin.arrayIndices"); - return AstUtil.newInvocation(iteratorFunName, receiver); - } -} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayIteratorIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayIteratorIntrinsic.java deleted file mode 100644 index cc04aa26246..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayIteratorIntrinsic.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.k2js.translate.intrinsic.array; - -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.util.AstUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; - -import java.util.List; - -/** - * @author Pavel Talanov - */ -public enum ArrayIteratorIntrinsic implements FunctionIntrinsic { - - INSTANCE; - - @NotNull - @Override - public JsExpression apply(@Nullable JsExpression receiver, @NotNull List arguments, - @NotNull TranslationContext context) { - assert receiver != null; - assert arguments.size() == 0; - //TODO: provide better mechanism - JsNameRef iteratorFunName = AstUtil.newQualifiedNameRef("Kotlin.arrayIterator"); - return AstUtil.newInvocation(iteratorFunName, receiver); - } -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayNullConstructorIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayNullConstructorIntrinsic.java deleted file mode 100644 index 3d590da0f2e..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayNullConstructorIntrinsic.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.k2js.translate.intrinsic.array; - -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.util.AstUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; - -import java.util.List; - -import static org.jetbrains.k2js.translate.utils.JsAstUtils.newInvocation; - -/** - * @author Pavel Talanov - */ -public enum ArrayNullConstructorIntrinsic implements FunctionIntrinsic { - - INSTANCE; - - //TODO: implement function passing to array constructor - @NotNull - @Override - public JsExpression apply(@Nullable JsExpression receiver, @NotNull List arguments, - @NotNull TranslationContext context) { - assert receiver == null; - assert arguments.size() == 1; - //TODO: provide better mechanism - JsNameRef nullArrayFunName = AstUtil.newQualifiedNameRef("Kotlin.nullArray"); - return newInvocation(nullArrayFunName, arguments); - } -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArraySetIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArraySetIntrinsic.java index 03f41d57c7c..773d6547dbf 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArraySetIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArraySetIntrinsic.java @@ -22,14 +22,14 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.List; /** * @author Pavel Talanov */ -public enum ArraySetIntrinsic implements FunctionIntrinsic { +public enum ArraySetIntrinsic implements Intrinsic { INSTANCE; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArraySizeIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/BuiltInPropertyIntrinsic.java similarity index 53% rename from js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArraySizeIntrinsic.java rename to js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/BuiltInPropertyIntrinsic.java index c1715d85b3f..10445c1921c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArraySizeIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/BuiltInPropertyIntrinsic.java @@ -1,19 +1,3 @@ -/* - * 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.k2js.translate.intrinsic.array; import com.google.dart.compiler.backend.js.ast.JsExpression; @@ -22,7 +6,7 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.List; @@ -31,10 +15,14 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier; /** * @author Pavel Talanov */ -public enum ArraySizeIntrinsic implements FunctionIntrinsic { +public final class BuiltInPropertyIntrinsic implements Intrinsic { - INSTANCE; + @NotNull + private final String propertyName; + public BuiltInPropertyIntrinsic(@NotNull String propertyName) { + this.propertyName = propertyName; + } @NotNull @Override @@ -43,8 +31,8 @@ public enum ArraySizeIntrinsic implements FunctionIntrinsic { assert receiver != null; assert arguments.isEmpty() : "Length expression must have zero arguments."; //TODO: provide better way - JsNameRef lengthProperty = AstUtil.newQualifiedNameRef("length"); + JsNameRef lengthProperty = AstUtil.newQualifiedNameRef(propertyName); setQualifier(lengthProperty, receiver); return lengthProperty; } -} +} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayFunctionConstructorIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/CallStandardMethodIntrinsic.java similarity index 52% rename from js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayFunctionConstructorIntrinsic.java rename to js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/CallStandardMethodIntrinsic.java index 2a025280241..d073fadf5a4 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/ArrayFunctionConstructorIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/array/CallStandardMethodIntrinsic.java @@ -16,13 +16,14 @@ package org.jetbrains.k2js.translate.intrinsic.array; +import com.google.common.collect.Lists; import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsNameRef; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.List; @@ -31,20 +32,42 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.newInvocation; /** * @author Pavel Talanov */ -public enum ArrayFunctionConstructorIntrinsic implements FunctionIntrinsic { +public final class CallStandardMethodIntrinsic implements Intrinsic { - INSTANCE; + @NotNull + private final String methodName; + private final boolean receiverShouldBeNotNull; + private final int expectedParamsNumber; + + public CallStandardMethodIntrinsic(@NotNull String methodName, boolean receiverShouldBeNotNull, int expectedParamsNumber) { + this.methodName = methodName; + this.receiverShouldBeNotNull = receiverShouldBeNotNull; + this.expectedParamsNumber = expectedParamsNumber; + } @NotNull @Override public JsExpression apply(@Nullable JsExpression receiver, @NotNull List arguments, @NotNull TranslationContext context) { - assert receiver == null; - assert arguments.size() == 2; - //TODO: provide better mechanism - JsNameRef iteratorFunName = AstUtil.newQualifiedNameRef("Kotlin.arrayFromFun"); - return newInvocation(iteratorFunName, arguments); + assert (receiver != null == receiverShouldBeNotNull); + assert arguments.size() == expectedParamsNumber; + List args = composeArguments(receiver, arguments); + JsNameRef iteratorFunName = AstUtil.newQualifiedNameRef(methodName); + return newInvocation(iteratorFunName, composeArguments(receiver, arguments)); } -} + + @NotNull + private static List composeArguments(@Nullable JsExpression receiver, @NotNull List arguments) { + if (receiver != null) { + List args = Lists.newArrayList(); + args.add(receiver); + args.addAll(arguments); + return args; + } + else { + return arguments; + } + } +} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveBinaryOperationIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveBinaryOperationIntrinsic.java index 5d6039319e9..2da91dff5a1 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveBinaryOperationIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveBinaryOperationIntrinsic.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import org.jetbrains.k2js.translate.operation.OperatorTable; import java.util.List; @@ -31,7 +31,7 @@ import java.util.List; /** * @author Pavel Talanov */ -public final class PrimitiveBinaryOperationIntrinsic implements FunctionIntrinsic { +public final class PrimitiveBinaryOperationIntrinsic implements Intrinsic { @NotNull public static PrimitiveBinaryOperationIntrinsic newInstance(@NotNull JetToken token) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveEqualsIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveEqualsIntrinsic.java index 3d95c2ca6b9..9d3140af8c7 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveEqualsIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveEqualsIntrinsic.java @@ -21,11 +21,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.intrinsic.EqualsIntrinsic; -import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.List; -import static org.jetbrains.k2js.translate.utils.JsAstUtils.notEqual; +import static org.jetbrains.k2js.translate.utils.JsAstUtils.equality; +import static org.jetbrains.k2js.translate.utils.JsAstUtils.inequality; /** * @author Pavel Talanov @@ -46,10 +46,10 @@ public final class PrimitiveEqualsIntrinsic extends EqualsIntrinsic { assert arguments.size() == 1 : "Equals operation should have one argument"; assert receiver != null; if (isNegated()) { - return notEqual(receiver, arguments.get(0)); + return inequality(receiver, arguments.get(0)); } else { - return JsAstUtils.equals(receiver, arguments.get(0)); + return equality(receiver, arguments.get(0)); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java index 3920ade7a2a..4bb5777266d 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java @@ -24,7 +24,7 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.List; @@ -33,7 +33,7 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; /** * @author Pavel Talanov */ -public final class PrimitiveRangeToIntrinsic implements FunctionIntrinsic { +public final class PrimitiveRangeToIntrinsic implements Intrinsic { @NotNull public static PrimitiveRangeToIntrinsic newInstance() { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveUnaryOperationIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveUnaryOperationIntrinsic.java index 817461472a3..8766549e5b7 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveUnaryOperationIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveUnaryOperationIntrinsic.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import org.jetbrains.k2js.translate.operation.OperatorTable; import java.util.List; @@ -31,7 +31,7 @@ import java.util.List; /** * @author Pavel Talanov */ -public final class PrimitiveUnaryOperationIntrinsic implements FunctionIntrinsic { +public final class PrimitiveUnaryOperationIntrinsic implements Intrinsic { @NotNull public static PrimitiveUnaryOperationIntrinsic newInstance(@NotNull JetToken token) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/string/CharAtIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/string/CharAtIntrinsic.java index 902cbf6f0dc..2cc4d9c2134 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/string/CharAtIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/string/CharAtIntrinsic.java @@ -22,7 +22,7 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.List; @@ -32,7 +32,7 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier; /** * @author Pavel Talanov */ -public enum CharAtIntrinsic implements FunctionIntrinsic { +public enum CharAtIntrinsic implements Intrinsic { INSTANCE; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/string/LengthIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/string/LengthIntrinsic.java deleted file mode 100644 index 510c9f938a2..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/string/LengthIntrinsic.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.k2js.translate.intrinsic.string; - - -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.util.AstUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; - -import java.util.List; - -import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier; - -/** - * @author Pavel Talanov - */ -public enum LengthIntrinsic implements FunctionIntrinsic { - - INSTANCE; - - @NotNull - @Override - public JsExpression apply(@Nullable JsExpression receiver, @NotNull List arguments, - @NotNull TranslationContext context) { - assert receiver != null; - assert arguments.isEmpty() : "Length expression must have zero arguments."; - //TODO: provide better way - JsNameRef lengthProperty = AstUtil.newQualifiedNameRef("length"); - setQualifier(lengthProperty, receiver); - return lengthProperty; - } -} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/tuple/TupleAccessIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/tuple/TupleAccessIntrinsic.java index 0dd7aa92dcb..4e8aa2d2ff0 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/tuple/TupleAccessIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/tuple/TupleAccessIntrinsic.java @@ -21,14 +21,14 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.List; /** * @author Pavel Talanov */ -public final class TupleAccessIntrinsic implements FunctionIntrinsic { +public final class TupleAccessIntrinsic implements Intrinsic { private final int elementIndex; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java index 85e3a978cbd..b987b7bddbe 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java @@ -33,8 +33,6 @@ import org.jetbrains.k2js.translate.intrinsic.EqualsIntrinsic; import org.jetbrains.k2js.translate.reference.CallBuilder; import org.jetbrains.k2js.translate.reference.CallType; -import java.util.Arrays; - import static org.jetbrains.k2js.translate.operation.AssignmentTranslator.isAssignmentOperator; import static org.jetbrains.k2js.translate.operation.CompareToTranslator.isCompareToCall; import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression; @@ -42,8 +40,7 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.isEquals; import static org.jetbrains.k2js.translate.utils.JsAstUtils.not; import static org.jetbrains.k2js.translate.utils.PsiUtils.*; -import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateLeftExpression; -import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRightExpression; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.*; /** @@ -105,9 +102,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator { assert operationDescriptor != null : "Equals operation must resolve to descriptor."; EqualsIntrinsic intrinsic = context().intrinsics().getEqualsIntrinsic(operationDescriptor); intrinsic.setNegated(expression.getOperationToken().equals(JetTokens.EXCLEQ)); - JsExpression left = translateLeftExpression(context(), expression); - JsExpression right = translateRightExpression(context(), expression); - return intrinsic.apply(left, Arrays.asList(right), context()); + return applyIntrinsicToBinaryExpression(context(), intrinsic, expression); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java index 3ce5449c216..8b346d023b1 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java @@ -29,12 +29,11 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.intrinsic.CompareToIntrinsic; import org.jetbrains.k2js.translate.utils.TranslationUtils; -import java.util.Arrays; - import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.isCompareTo; import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken; -import static org.jetbrains.k2js.translate.utils.TranslationUtils.*; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.applyIntrinsicToBinaryExpression; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.isIntrinsicOperation; /** * @author Pavel Talanov @@ -93,8 +92,7 @@ public final class CompareToTranslator extends AbstractTranslator { private JsExpression intrinsicCompareTo() { CompareToIntrinsic intrinsic = context().intrinsics().getCompareToIntrinsic(descriptor); intrinsic.setComparisonToken((JetToken) expression.getOperationToken()); - JsExpression left = translateLeftExpression(context(), expression); - JsExpression right = translateRightExpression(context(), expression); - return intrinsic.apply(left, Arrays.asList(right), context()); + return applyIntrinsicToBinaryExpression(context(), intrinsic, expression); } + } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java index cd6e096c1cf..34c052cbe8e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java @@ -29,7 +29,7 @@ import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; -import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import org.jetbrains.k2js.translate.utils.AnnotationsUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils; @@ -121,10 +121,10 @@ public final class CallTranslator extends AbstractTranslator { @NotNull private JsExpression intrinsicInvocation() { assert descriptor instanceof FunctionDescriptor; - FunctionIntrinsic functionIntrinsic = + Intrinsic intrinsic = context().intrinsics().getFunctionIntrinsic((FunctionDescriptor) descriptor); JsExpression receiverExpression = resolveThisObject(/*do not get qualifier*/false); - return functionIntrinsic.apply(receiverExpression, arguments, context()); + return intrinsic.apply(receiverExpression, arguments, context()); } private boolean isConstructor() { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallType.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallType.java index 19510c0e5e4..a4f0fcc74a8 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallType.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallType.java @@ -27,9 +27,9 @@ import org.jetbrains.jet.lang.psi.JetQualifiedExpression; import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression; import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.utils.TranslationUtils; import static com.google.dart.compiler.util.AstUtil.newSequence; -import static org.jetbrains.k2js.translate.utils.JsAstUtils.notEqual; /** * @author Pavel Talanov @@ -42,11 +42,10 @@ public enum CallType { @NotNull TranslationContext context) { assert receiver != null; TemporaryVariable temporaryVariable = context.declareTemporary(receiver); + JsBinaryOperation notNullCheck = TranslationUtils.notNullCheck(context, temporaryVariable.reference()); JsNullLiteral nullLiteral = context.program().getNullLiteral(); - //TODO: find similar not null checks - JsBinaryOperation notNullCheck = notEqual(temporaryVariable.reference(), nullLiteral); - JsConditional callMethodIfNotNullElseNull = - new JsConditional(notNullCheck, constructor.construct(temporaryVariable.reference()), nullLiteral); + JsExpression methodCall = constructor.construct(temporaryVariable.reference()); + JsConditional callMethodIfNotNullElseNull = new JsConditional(notNullCheck, methodCall, nullLiteral); return newSequence(temporaryVariable.assignmentExpression(), callMethodIfNotNullElseNull); } }, diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 636d0e6b9ff..0e02c4b1114 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -205,6 +205,7 @@ public final class BindingUtils { } + //TODO: refactor duplication //TODO: check where we use there, suspicious public static boolean isOwnedByNamespace(@NotNull DeclarationDescriptor descriptor) { if (descriptor instanceof ConstructorDescriptor) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java index a1b115b1916..f2cdff1975c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java @@ -19,9 +19,10 @@ package org.jetbrains.k2js.translate.utils; import com.google.common.collect.Lists; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -130,18 +131,18 @@ public final class JsAstUtils { } @NotNull - public static JsBinaryOperation equals(@NotNull JsExpression arg1, @NotNull JsExpression arg2) { + public static JsBinaryOperation equality(@NotNull JsExpression arg1, @NotNull JsExpression arg2) { return new JsBinaryOperation(JsBinaryOperator.EQ, arg1, arg2); } @NotNull - public static JsBinaryOperation notEqual(@NotNull JsExpression arg1, @NotNull JsExpression arg2) { + public static JsBinaryOperation inequality(@NotNull JsExpression arg1, @NotNull JsExpression arg2) { return new JsBinaryOperation(JsBinaryOperator.NEQ, arg1, arg2); } @NotNull public static JsExpression equalsTrue(@NotNull JsExpression expression, @NotNull JsProgram program) { - return equals(expression, program.getTrueLiteral()); + return equality(expression, program.getTrueLiteral()); } @NotNull @@ -154,6 +155,11 @@ public final class JsAstUtils { return new JsBinaryOperation(JsBinaryOperator.ADD, left, right); } + @NotNull + public static JsBinaryOperation addAssign(@NotNull JsExpression left, @NotNull JsExpression right) { + return new JsBinaryOperation(JsBinaryOperator.ASG_ADD, left, right); + } + @NotNull public static JsBinaryOperation subtract(@NotNull JsExpression left, @NotNull JsExpression right) { return new JsBinaryOperation(JsBinaryOperator.SUB, left, right); @@ -166,7 +172,37 @@ public final class JsAstUtils { @NotNull public static JsBinaryOperation typeof(@NotNull JsExpression expression, @NotNull JsStringLiteral string) { - return equals(new JsPrefixOperation(JsUnaryOperator.TYPEOF, expression), string); + return equality(new JsPrefixOperation(JsUnaryOperator.TYPEOF, expression), string); + } + + @NotNull + public static JsFor generateForExpression(@NotNull JsVars initExpression, + @NotNull JsExpression condition, + @NotNull JsExpression incrExpression, + @NotNull JsStatement body) { + JsFor result = new JsFor(); + result.setInitVars(initExpression); + result.setCondition(condition); + result.setIncrExpr(incrExpression); + result.setBody(body); + return result; + } + + public static boolean ownsName(@NotNull JsScope scope, @NotNull JsName name) { + Iterator nameIterator = scope.getAllNames(); + while (nameIterator.hasNext()) { + if (nameIterator.next() == name) { + return true; + } + } + return false; + } + + @NotNull + public static JsObjectLiteral newObjectLiteral(@NotNull List propertyList) { + JsObjectLiteral jsObjectLiteral = new JsObjectLiteral(); + jsObjectLiteral.getPropertyInitializers().addAll(propertyList); + return jsObjectLiteral; } public interface Mutator { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java index 899a8365ae3..676bf5e5a53 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java @@ -24,8 +24,10 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.Translation; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.jetbrains.k2js.translate.utils.BindingUtils.*; @@ -44,14 +46,14 @@ public final class TranslationUtils { public static JsBinaryOperation notNullCheck(@NotNull TranslationContext context, @NotNull JsExpression expressionToCheck) { JsNullLiteral nullLiteral = context.program().getNullLiteral(); - return notEqual(expressionToCheck, nullLiteral); + return inequality(expressionToCheck, nullLiteral); } @NotNull public static JsBinaryOperation isNullCheck(@NotNull TranslationContext context, @NotNull JsExpression expressionToCheck) { JsNullLiteral nullLiteral = context.program().getNullLiteral(); - return JsAstUtils.equals(expressionToCheck, nullLiteral); + return equality(expressionToCheck, nullLiteral); } @NotNull @@ -71,14 +73,6 @@ public final class TranslationUtils { return Translation.translateAsExpression(jetExpression, context); } - //TODO: refactor backing field reference generation to use the generic way - @NotNull - public static JsNameRef backingFieldReference(@NotNull TranslationContext context, - @NotNull JetProperty expression) { - PropertyDescriptor propertyDescriptor = getPropertyDescriptor(context.bindingContext(), expression); - return backingFieldReference(context, propertyDescriptor); - } - @NotNull public static JsNameRef backingFieldReference(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) { @@ -164,14 +158,6 @@ public final class TranslationUtils { return Translation.translateAsExpression(baseExpression, context); } - //TODO: - @NotNull - public static JsExpression translateReceiver(@NotNull TranslationContext context, - @NotNull JetDotQualifiedExpression expression) { - return Translation.translateAsExpression(expression.getReceiverExpression(), context); - } - - @NotNull public static JsExpression translateLeftExpression(@NotNull TranslationContext context, @NotNull JetBinaryExpression expression) { @@ -227,4 +213,12 @@ public final class TranslationUtils { context.aliaser().removeAliasForThis(descriptor); } + @NotNull + public static JsExpression applyIntrinsicToBinaryExpression(@NotNull TranslationContext context, + @NotNull Intrinsic intrinsic, + @NotNull JetBinaryExpression binaryExpression) { + JsExpression left = translateLeftExpression(context, binaryExpression); + JsExpression right = translateRightExpression(context, binaryExpression); + return intrinsic.apply(left, Arrays.asList(right), context); + } } diff --git a/lib/asm-all-3.3.1.jar b/lib/asm-all-3.3.1.jar new file mode 100644 index 00000000000..df03b326614 Binary files /dev/null and b/lib/asm-all-3.3.1.jar differ diff --git a/lib/asm-util-3.3.1.jar b/lib/asm-util-3.3.1.jar deleted file mode 100644 index 0230bbcfb71..00000000000 Binary files a/lib/asm-util-3.3.1.jar and /dev/null differ diff --git a/update_dependencies.xml b/update_dependencies.xml index febea7ad77f..8132cbe6065 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -13,8 +13,12 @@ + + + +