diff --git a/_toc.yml b/_toc.yml index 9a55b3b..9d4f64e 100644 --- a/_toc.yml +++ b/_toc.yml @@ -4,6 +4,7 @@ format: jb-book root: docs/intro chapters: -- file: notebooks/1_crawl_reviews +- file: notebooks/1_collect_reviews - file: notebooks/2_inference - file: notebooks/3_evaluation +- file: docs/conclusion diff --git a/data/JetBrains_kotlin_1000.csv b/data/JetBrains_kotlin_1000.csv new file mode 100644 index 0000000..e079917 --- /dev/null +++ b/data/JetBrains_kotlin_1000.csv @@ -0,0 +1,60511 @@ +,diff_hunk,human_review,created_at +946,"@@ -0,0 +1 @@ ++org.jetbrains.kotlin.idea.inspections.RemoveRedundantBackticksInspection",Please add a test to verify that the quickfix is not offered when an actual keyword is in backticks.,2017-08-03 11:03:49 +46,"@@ -0,0 +1 @@ ++throw Exception(""not implemented"") //To change body of created methods use File | Settings | File Templates.","`UnsupportedOperationException` would be a better choice +",2013-04-26 11:06:35 +51,"@@ -0,0 +1,10 @@ ++// ""Create class object from usage"" ""true"" ++// ERROR: Expression 'T' of type '' cannot be invoked as a function ++trait T { ++ class object { ++ }","Can you come up with better use case for quick fix creating class object? This one from the test doesn't seem useful. + +Creating class object via intetion could be useful in case of T.foo() call, but in this case foo() function should be created as well (actually, it should be ""create function from usage"" quick fix, not ""create class object from usage""). +",2013-04-26 11:16:26 +958,"@@ -0,0 +1,10 @@ ++open class Foo { ++ open fun arguments(arg1: Int, arg2: Long) { ++ } ++} ++ ++class Bar : Foo() { ++ override fun arguments(arg1: Int, arg2: Long) {","I should mention that overridden function is not redundant if it has some other modifiers. For example, sometimes is reasonable to add `final` here, so function itself is not changed, but derived classes are made unable to override it. Also, I think that any annotation here makes the function not redundant. The same for any visibility modifier when you make overridden function more visible then original one. Please consider these cases, fix inspection, and add tests for them.",2017-08-14 10:22:17 +190,"@@ -0,0 +1,101 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ //val expectedType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element.getFunctionLiteral()] ++ //println(""expected type of the function literal is "" + expectedType) ++ //val expectedType2 = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element] ++ //println(""expected type of the function literal exp is "" + expectedType2) ++ ++ if (hasExplicitReturnType(element)) return true ++ if (hasExplicitReceiverType(element)) return true ++ if (hasExplicitParamType(element)) return true ++ return false","A one-liner would be nicer in my opinion: +`return hasExplicitReturnType(element) || hasExplicitReceiverType(element) || hasExplicitParamType(element)` +",2014-04-21 19:05:28 +189,"@@ -0,0 +1,101 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ //val expectedType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element.getFunctionLiteral()] ++ //println(""expected type of the function literal is "" + expectedType) ++ //val expectedType2 = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element] ++ //println(""expected type of the function literal exp is "" + expectedType2) ++ ++ if (hasExplicitReturnType(element)) return true ++ if (hasExplicitReceiverType(element)) return true ++ if (hasExplicitParamType(element)) return true ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ val oldParameters = oldParameterList?.getParameters() ++ if (oldParameterList != null && oldParameters != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameters.map({(parameter: JetParameter): String -> parameter.getNameIdentifier()?.getText() ?: parameter.getText() ?: """"","Are all three sub-expressions of this elvis expression tested? +",2014-04-21 19:02:50 +188,"@@ -0,0 +1,101 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ //val expectedType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element.getFunctionLiteral()] ++ //println(""expected type of the function literal is "" + expectedType) ++ //val expectedType2 = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element] ++ //println(""expected type of the function literal exp is "" + expectedType2) ++ ++ if (hasExplicitReturnType(element)) return true ++ if (hasExplicitReceiverType(element)) return true ++ if (hasExplicitParamType(element)) return true ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ val oldParameters = oldParameterList?.getParameters() ++ if (oldParameterList != null && oldParameters != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameters.map({(parameter: JetParameter): String -> parameter.getNameIdentifier()?.getText() ?: parameter.getText() ?: """" ++ }).makeString("", "", ""("", "")"") ++ println(""parameterString is "" + parameterString)","Don't forget to delete all debug output from your changeset +",2014-04-21 19:00:15 +191,"@@ -0,0 +1,101 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ //val expectedType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element.getFunctionLiteral()] ++ //println(""expected type of the function literal is "" + expectedType) ++ //val expectedType2 = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element] ++ //println(""expected type of the function literal exp is "" + expectedType2) ++ ++ if (hasExplicitReturnType(element)) return true ++ if (hasExplicitReceiverType(element)) return true ++ if (hasExplicitParamType(element)) return true ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ val oldParameters = oldParameterList?.getParameters() ++ if (oldParameterList != null && oldParameters != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameters.map({(parameter: JetParameter): String -> parameter.getNameIdentifier()?.getText() ?: parameter.getText() ?: """" ++ }).makeString("", "", ""("", "")"") ++ println(""parameterString is "" + parameterString) ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ oldParameterList.replace(newParameterList) ++ } ++ ++ if (!hasExplicitParamType(element)) { ++ val currentParamList = element.getFunctionLiteral().getValueParameterList() ++ val firstChild = currentParamList?.getFirstChild() ++ if (firstChild?.getText() == ""("") firstChild!!.delete()","It's not very acceptable to compare text of nodes, especially when you can do the same structurally: +`firstChild.getElementType() == JetTokens.LPAR` +",2014-04-21 19:11:58 +192,"@@ -0,0 +1,101 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ //val expectedType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element.getFunctionLiteral()] ++ //println(""expected type of the function literal is "" + expectedType) ++ //val expectedType2 = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element] ++ //println(""expected type of the function literal exp is "" + expectedType2) ++ ++ if (hasExplicitReturnType(element)) return true ++ if (hasExplicitReceiverType(element)) return true ++ if (hasExplicitParamType(element)) return true ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ val oldParameters = oldParameterList?.getParameters() ++ if (oldParameterList != null && oldParameters != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameters.map({(parameter: JetParameter): String -> parameter.getNameIdentifier()?.getText() ?: parameter.getText() ?: """" ++ }).makeString("", "", ""("", "")"") ++ println(""parameterString is "" + parameterString) ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ oldParameterList.replace(newParameterList) ++ } ++ ++ if (!hasExplicitParamType(element)) { ++ val currentParamList = element.getFunctionLiteral().getValueParameterList() ++ val firstChild = currentParamList?.getFirstChild() ++ if (firstChild?.getText() == ""("") firstChild!!.delete() ++ val lastChild = currentParamList?.getLastChild() ++ if (lastChild?.getText() == "")"") lastChild!!.delete()","Ditto (`JetTokens.RPAR`) +",2014-04-21 19:12:11 +987,"@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.effectsystem.impls.* ++import org.jetbrains.kotlin.effectsystem.structure.ESClause ++import org.jetbrains.kotlin.effectsystem.structure.ESEffect ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.structure.ESExpressionVisitor ++ ++class InfoCollector(private val observedEffect: ESEffect) : ESExpressionVisitor { ++ private var isInverted: Boolean = false ++ ++ fun collectFromSchema(schema: EffectSchema): MutableContextInfo = ++ schema.clauses.mapNotNull { collectFromClause(it) }.fold(MutableContextInfo.EMPTY, { resultingInfo, clauseInfo -> resultingInfo.and(clauseInfo) }) ++ ++ private fun collectFromClause(clause: ESClause): MutableContextInfo? { ++ val premise = clause.condition",This name contradicts with real semantics,2017-08-15 16:57:17 +986,"@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.effectsystem.impls.* ++import org.jetbrains.kotlin.effectsystem.structure.ESClause ++import org.jetbrains.kotlin.effectsystem.structure.ESEffect ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.structure.ESExpressionVisitor ++ ++class InfoCollector(private val observedEffect: ESEffect) : ESExpressionVisitor { ++ private var isInverted: Boolean = false ++ ++ fun collectFromSchema(schema: EffectSchema): MutableContextInfo = ++ schema.clauses.mapNotNull { collectFromClause(it) }.fold(MutableContextInfo.EMPTY, { resultingInfo, clauseInfo -> resultingInfo.and(clauseInfo) }) ++ ++ private fun collectFromClause(clause: ESClause): MutableContextInfo? { ++ val premise = clause.condition ++ ++ // Check for non-conditional effects ++ if (premise is ESBooleanConstant && premise.value) { ++ return MutableContextInfo.EMPTY.fire(clause.effect)","As we have discussed, logically this conclusion is erroneous. I strongly recommend to fix this, because you can create true clause condition in some other context thus getting really wrong conclusion",2017-08-15 16:56:49 +989,"@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.effectsystem.impls.* ++import org.jetbrains.kotlin.effectsystem.structure.ESClause ++import org.jetbrains.kotlin.effectsystem.structure.ESEffect ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.structure.ESExpressionVisitor ++ ++class InfoCollector(private val observedEffect: ESEffect) : ESExpressionVisitor { ++ private var isInverted: Boolean = false ++ ++ fun collectFromSchema(schema: EffectSchema): MutableContextInfo = ++ schema.clauses.mapNotNull { collectFromClause(it) }.fold(MutableContextInfo.EMPTY, { resultingInfo, clauseInfo -> resultingInfo.and(clauseInfo) }) ++ ++ private fun collectFromClause(clause: ESClause): MutableContextInfo? { ++ val premise = clause.condition ++ ++ // Check for non-conditional effects ++ if (premise is ESBooleanConstant && premise.value) { ++ return MutableContextInfo.EMPTY.fire(clause.effect) ++ } ++ ++ // Check for information from conditional effects ++ return when (observedEffect.isImplies(clause.effect)) { ++ // observed effect implies clause's effect => clause's effect was fired => clause's condition is true ++ true -> clause.condition.accept(this) ++ ++ // Observed effect *may* or *doesn't* implies clause's - no useful information ++ null, false -> null ++ } ++ } ++ ++ override fun visitIs(isOperator: ESIs): MutableContextInfo = with(isOperator) { ++ if (isNegated != isInverted) MutableContextInfo.EMPTY.notSubtype(left, type) else MutableContextInfo.EMPTY.subtype(left, type) ++ } ++ ++ override fun visitEqual(equal: ESEqual): MutableContextInfo = with(equal) { ++ if (isNegated != isInverted) MutableContextInfo.EMPTY.notEqual(left, right) else MutableContextInfo.EMPTY.equal(left, right) ++ } ++ ++ override fun visitAnd(and: ESAnd): MutableContextInfo { ++ val leftInfo = and.left.accept(this) ++ val rightInfo = and.right.accept(this) ++ ++ return if (isInverted) leftInfo.or(rightInfo) else leftInfo.and(rightInfo) ++ } ++ ++ override fun visitNot(not: ESNot): MutableContextInfo = inverted { not.arg.accept(this) } ++ ++ override fun visitOr(or: ESOr): MutableContextInfo { ++ val leftInfo = or.left.accept(this) ++ val rightInfo = or.right.accept(this) ++ return if (isInverted) leftInfo.and(rightInfo) else leftInfo.or(rightInfo) ++ } ++ ++ override fun visitVariable(esVariable: ESVariable): MutableContextInfo { ++ throw IllegalStateException(""InfoCollector shouldn't visit non-boolean values"") ++ } ++ ++ override fun visitBooleanVariable(esBooleanVariable: ESBooleanVariable): MutableContextInfo = ++ if (isInverted) ++ MutableContextInfo.EMPTY.equal(esBooleanVariable, false.lift()) ++ else ++ MutableContextInfo.EMPTY.equal(esBooleanVariable, true.lift()) ++ ++ override fun visitBooleanConstant(esBooleanConstant: ESBooleanConstant): MutableContextInfo { ++ throw IllegalStateException(""InfoCollector shouldn't visit constants"") ++ } ++ ++ override fun visitConstant(esConstant: ESConstant): MutableContextInfo { ++ throw IllegalStateException(""InfoCollector shouldn't visit constants"") ++ } ++ ++ override fun visitLambda(esLambda: ESLambda): MutableContextInfo { ++ throw IllegalStateException(""InfoCollector shouldn't visit non-boolean values"") ++ } ++ ++ private fun inverted(block: () -> R): R { ++ isInverted = isInverted.not() ++ val result = block() ++ isInverted = isInverted.not()",Ugly construction. Are you sure it's really needed?,2017-08-15 17:03:26 +999,"@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression ++ ++class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (!function.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return ++ if (function.containsOtherModifier()) return",I'd inline this function,2017-08-18 08:16:24 +998,"@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression ++ ++class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (!function.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return ++ if (function.containsOtherModifier()) return ++ if (function.annotationEntries.size != 0) return ++ ++ val bodyExpression = function.bodyExpression ++ bodyExpression ?: return",This and previous can be written in one line,2017-08-18 08:16:15 +483,"@@ -0,0 +1,103 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.resolve ++ ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.descriptors.* ++import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor ++import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget ++import org.jetbrains.kotlin.descriptors.annotations.Annotations ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.resolve.annotations.argumentValue ++ ++private val JAVA_DEPRECATED = FqName(Deprecated::class.java.name)","This was corrupted by the refactoring and is now in fact ""kotlin.Deprecated"". Let's use a hard-coded string instead. +",2015-10-10 20:41:17 +979,"@@ -0,0 +1,103 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.visitors ++ ++import org.jetbrains.kotlin.effectsystem.factories.boundSchemaFromClauses ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.factories.negated ++import org.jetbrains.kotlin.effectsystem.impls.* ++import org.jetbrains.kotlin.effectsystem.structure.* ++import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf ++ ++/** ++ * Reduces given effect schema by evaluating constant expressions, ++ * throwing away senseless checks and infeasible clauses, etc. ++ */ ++class Reducer : ESExpressionVisitor { ++ fun reduceSchema(schema: EffectSchema): EffectSchema = ++ boundSchemaFromClauses(schema.clauses.mapNotNull { reduceClause(it) }) ++ ++ private fun reduceClause(clause: org.jetbrains.kotlin.effectsystem.structure.ESClause): org.jetbrains.kotlin.effectsystem.structure.ESClause? {",Fully qualified names for some reason,2017-08-15 16:39:16 +980,"@@ -0,0 +1,103 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.visitors ++ ++import org.jetbrains.kotlin.effectsystem.factories.boundSchemaFromClauses ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.factories.negated ++import org.jetbrains.kotlin.effectsystem.impls.* ++import org.jetbrains.kotlin.effectsystem.structure.* ++import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf ++ ++/** ++ * Reduces given effect schema by evaluating constant expressions, ++ * throwing away senseless checks and infeasible clauses, etc. ++ */ ++class Reducer : ESExpressionVisitor { ++ fun reduceSchema(schema: EffectSchema): EffectSchema = ++ boundSchemaFromClauses(schema.clauses.mapNotNull { reduceClause(it) }) ++ ++ private fun reduceClause(clause: org.jetbrains.kotlin.effectsystem.structure.ESClause): org.jetbrains.kotlin.effectsystem.structure.ESClause? { ++ val reducedPremise = clause.condition.accept(this) as ESBooleanExpression ++ ++ // Filter never executed premises ++ return if (reducedPremise is ESBooleanConstant && !reducedPremise.value) null else ESClause(reducedPremise, clause.effect)",I don't like this `null` because its meaning is unclear. It's better to introduce thing like `ESFalseClause`.,2017-08-15 16:42:36 +981,"@@ -0,0 +1,103 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.visitors ++ ++import org.jetbrains.kotlin.effectsystem.factories.boundSchemaFromClauses ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.factories.negated ++import org.jetbrains.kotlin.effectsystem.impls.* ++import org.jetbrains.kotlin.effectsystem.structure.* ++import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf ++ ++/** ++ * Reduces given effect schema by evaluating constant expressions, ++ * throwing away senseless checks and infeasible clauses, etc. ++ */ ++class Reducer : ESExpressionVisitor { ++ fun reduceSchema(schema: EffectSchema): EffectSchema = ++ boundSchemaFromClauses(schema.clauses.mapNotNull { reduceClause(it) }) ++ ++ private fun reduceClause(clause: org.jetbrains.kotlin.effectsystem.structure.ESClause): org.jetbrains.kotlin.effectsystem.structure.ESClause? { ++ val reducedPremise = clause.condition.accept(this) as ESBooleanExpression ++ ++ // Filter never executed premises ++ return if (reducedPremise is ESBooleanConstant && !reducedPremise.value) null else ESClause(reducedPremise, clause.effect) ++ } ++ ++ override fun visitIs(isOperator: ESIs): ESBooleanExpression { ++ val reducedArg = isOperator.left.accept(this) as ESValue ++ ++ val result = when (reducedArg) { ++ is ESConstant -> reducedArg.type.isSubtypeOf(isOperator.functor.type) ++ is ESVariable -> if (reducedArg.type.isSubtypeOf(isOperator.functor.type)) true else null ++ else -> throw IllegalStateException(""Unknown subtype of ESValue: $reducedArg"") ++ } ++ ++ // Result is unknown, do not evaluate ++ result ?: return ESIs(reducedArg, isOperator.functor) ++ ++ return result.xor(isOperator.functor.isNegated).lift() ++ } ++ ++ override fun visitEqual(equal: ESEqual): ESBooleanExpression { ++ val reducedLeft = equal.left.accept(this) as ESValue ++ val reducedRight = equal.right ++ ++ if (reducedLeft is ESConstant) return (reducedLeft.value == reducedRight.value).xor(equal.functor.isNegated).lift()","Just to ask: how does it work with different kinds of comparisons (`==`, `===`)?",2017-08-15 16:44:06 +711,"@@ -0,0 +1,104 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import com.intellij.psi.CommonClassNames ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.ElementKind ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++import javax.lang.model.element.VariableElement ++import javax.lang.model.type.NoType ++import javax.lang.model.type.TypeKind ++ ++class JavacClass(element: T, ++ javac: Javac) : JavacClassifier(element, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(element.simpleName.toString()) ++ ++ override val isAbstract ++ get() = element.isAbstract ++ ++ override val isStatic ++ get() = element.isStatic ++ ++ override val isFinal ++ get() = element.isFinal ++ ++ override val visibility ++ get() = element.getVisibility() ++ ++ override val typeParameters: List ++ get() = element.typeParameters.map { JavacTypeParameter(it, javac) } ++ ++ override val fqName ++ get() = FqName(element.qualifiedName.toString()) ++ ++ override val supertypes ++ get() = element.interfaces.toMutableList().apply { ++ if (element.superclass !is NoType) add(element.superclass) ++ ++ val hasObject = !none { it.toString() == CommonClassNames.JAVA_LANG_OBJECT } ++ if (!hasObject && element.toString() != CommonClassNames.JAVA_LANG_OBJECT) { ++ javac.JAVA_LANG_OBJECT?.let { add(it.element.asType()) }",Should we do it if a class already has a super class?,2017-04-05 14:49:17 +712,"@@ -0,0 +1,104 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import com.intellij.psi.CommonClassNames ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.ElementKind ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++import javax.lang.model.element.VariableElement ++import javax.lang.model.type.NoType ++import javax.lang.model.type.TypeKind ++ ++class JavacClass(element: T, ++ javac: Javac) : JavacClassifier(element, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(element.simpleName.toString()) ++ ++ override val isAbstract ++ get() = element.isAbstract ++ ++ override val isStatic ++ get() = element.isStatic ++ ++ override val isFinal ++ get() = element.isFinal ++ ++ override val visibility ++ get() = element.getVisibility() ++ ++ override val typeParameters: List ++ get() = element.typeParameters.map { JavacTypeParameter(it, javac) } ++ ++ override val fqName ++ get() = FqName(element.qualifiedName.toString()) ++ ++ override val supertypes ++ get() = element.interfaces.toMutableList().apply { ++ if (element.superclass !is NoType) add(element.superclass) ++ ++ val hasObject = !none { it.toString() == CommonClassNames.JAVA_LANG_OBJECT } ++ if (!hasObject && element.toString() != CommonClassNames.JAVA_LANG_OBJECT) { ++ javac.JAVA_LANG_OBJECT?.let { add(it.element.asType()) } ++ } ++ }.map { JavacClassifierType(it, javac) } ++ ++ override val innerClasses ++ get() = element.enclosedElements ++ .filter { it.asType().kind == TypeKind.DECLARED } ++ .filterIsInstance(TypeElement::class.java) ++ .map { JavacClass(it, javac) } ++ ++ override val outerClass: JavaClass? ++ get() = element.enclosingElement?.let { ++ if (it.asType().kind != TypeKind.DECLARED) null else JavacClass(it as TypeElement, javac) ++ } ++ ++ override val isInterface ++ get() = element.kind == ElementKind.INTERFACE ++ ++ override val isAnnotationType ++ get() = element.kind == ElementKind.ANNOTATION_TYPE ++ ++ override val isEnum ++ get() = element.kind == ElementKind.ENUM ++ ++ override val lightClassOriginKind = null ++ ++ override val methods: Collection ++ get() = element.enclosedElements","Here (and for many other properties) getters are in use. Are you sure this property is read just a few times and we do not spend too much time here? As a possible alternative, you can use `by lazy`.",2017-04-05 14:53:38 +31,"@@ -0,0 +1,105 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.TemplateBuilder; ++import com.intellij.codeInsight.template.TemplateBuilderFactory; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.ClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++import java.util.Collection; ++import java.util.LinkedHashSet; ++ ++public class MapPlatformClassToKotlinFix extends JetIntentionAction { ++ LinkedHashSet possibleTypes; ++ ++ public MapPlatformClassToKotlinFix(@NotNull JetUserType element, LinkedHashSet possibleTypes) { ++ super(element); ++ this.possibleTypes = possibleTypes; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return possibleTypes.size() == 1 ++ ? JetBundle.message(""map.platform.class.to.kotlin"", element.getText(), possibleTypes.iterator().next()) ++ : JetBundle.message(""map.platform.class.to.kotlin.multiple"", element.getText()); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""map.platform.class.to.kotlin.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ JetTypeReference newType = JetPsiFactory.createType(project, possibleTypes.iterator().next()); ++ JetTypeElement newTypeElement = newType.getTypeElement(); ++ assert newTypeElement != null; ++ PsiElement replacedElement = element.replace(newTypeElement); ++ ++ if (possibleTypes.size() > 1) { ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); ++ TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(replacedElement); ++ builder.replaceElement(replacedElement, new MyLookupExpression(replacedElement.getText(), possibleTypes, null, false, getText())); ++ builder.run(editor, true); ++ } ++ } ++ ++ public static JetIntentionActionFactory createFactory() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetUserType type = QuickFixUtil.getParentElementOfType(diagnostic, JetUserType.class); ++ if (type == null) return null; ++ ++ if (!(diagnostic instanceof DiagnosticWithParameters1)) return null;","It would be better to assert type of diagnostic.getFactory() at the begining, and cast diagnostic to DiagnosticWithParameters1>. See AddStarProjectionsFix. Don't forget to supress unchecked warning in this case. +",2013-02-21 13:43:35 +3,"@@ -0,0 +1,105 @@ ++ ++ ++ 4.0.0 ++ ++ org.jetbrains.kotlin.it ++ test-helloworld ++ 1.0 ++ Test Hello World project ++ ++ ++ Test the kotlin-maven-plugin:compile goal on HelloWorld project. ++ ++ ++ ++ 0.1-SNAPSHOT ++ ++ ++ ++ ++ junit ++ junit ++ 4.9 ++ ++ ++ ++ ++ ++ ${project.basedir}/src/main/kotlin ++ ++ ++ ++ ++ kotlin-maven-plugin ++ org.jetbrains.kotlin ++ ${kotlin.version} ++ ++ ++ compile ++ process-sources ++ ++ compile ++ ++ ++ ++ test-compile ++ process-test-sources ++ ++ test-compile ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ jetbrains-release ++ http://repository.jetbrains.com/releases ++ ++ true ++ ++ ++ false ++ ++ ++ ++ jetbrains-snapshots ++ http://repository.jetbrains.com/kotlin-snapshots ++ ++ false ++ ++ ++ true ++ ++ ++ ++ ++ ++ ","Do we need all those repositories here? +",2012-05-08 15:33:08 +390,"@@ -0,0 +1,107 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.idea.findUsages.handlers ++ ++import com.intellij.find.findUsages.FindUsagesHandler ++import com.intellij.find.findUsages.FindUsagesOptions ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiReference ++import com.intellij.psi.search.GlobalSearchScope ++import com.intellij.psi.search.SearchScope ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory ++import org.jetbrains.kotlin.idea.util.application.runReadAction ++ ++import java.util.ArrayList ++import java.util.Collections ++ ++public abstract class KotlinFindUsagesHandler(psiElement: T, ++ private val elementsToSearch: Collection, ++ public val factory: KotlinFindUsagesHandlerFactory) ++ : FindUsagesHandler(psiElement) { ++ ++ @suppress(""UNCHECKED_CAST"") ++ public fun getElement(): T { ++ return getPsiElement() as T ++ } ++ ++ public constructor(psiElement: T, factory: KotlinFindUsagesHandlerFactory) : this(psiElement, emptyList(), factory) { ++ } ++ ++ override fun getPrimaryElements(): Array { ++ return if (elementsToSearch.isEmpty()) ++ arrayOf(getPsiElement()) ++ else ++ elementsToSearch.toTypedArray() ++ } ++ ++ protected fun searchTextOccurrences(element: PsiElement, processor: Processor, options: FindUsagesOptions): Boolean { ++ val scope = options.searchScope ++ ++ val searchText = options.isSearchForTextOccurrences && scope is GlobalSearchScope","If you inline this variable, you can get rid of `as` operators below. +",2015-07-13 20:54:57 +391,"@@ -0,0 +1,107 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.idea.findUsages.handlers ++ ++import com.intellij.find.findUsages.FindUsagesHandler ++import com.intellij.find.findUsages.FindUsagesOptions ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiReference ++import com.intellij.psi.search.GlobalSearchScope ++import com.intellij.psi.search.SearchScope ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory ++import org.jetbrains.kotlin.idea.util.application.runReadAction ++ ++import java.util.ArrayList ++import java.util.Collections ++ ++public abstract class KotlinFindUsagesHandler(psiElement: T, ++ private val elementsToSearch: Collection, ++ public val factory: KotlinFindUsagesHandlerFactory) ++ : FindUsagesHandler(psiElement) { ++ ++ @suppress(""UNCHECKED_CAST"") ++ public fun getElement(): T { ++ return getPsiElement() as T ++ } ++ ++ public constructor(psiElement: T, factory: KotlinFindUsagesHandlerFactory) : this(psiElement, emptyList(), factory) { ++ } ++ ++ override fun getPrimaryElements(): Array { ++ return if (elementsToSearch.isEmpty()) ++ arrayOf(getPsiElement()) ++ else ++ elementsToSearch.toTypedArray() ++ } ++ ++ protected fun searchTextOccurrences(element: PsiElement, processor: Processor, options: FindUsagesOptions): Boolean { ++ val scope = options.searchScope ++ ++ val searchText = options.isSearchForTextOccurrences && scope is GlobalSearchScope ++ ++ if (searchText) { ++ if (options.fastTrack != null) {","If you revert this condition, you can get rid of `else`. +",2015-07-13 20:56:29 +27,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.ClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.JetClass; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lexer.JetKeywordToken; ++import org.jetbrains.jet.lexer.JetToken; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; ++ ++import static org.jetbrains.jet.lexer.JetTokens.FINAL_KEYWORD; ++import static org.jetbrains.jet.lexer.JetTokens.OPEN_KEYWORD; ++ ++public class FinalSupertypeFix extends JetIntentionAction { ++ private final JetClass childClass; ++ private JetClass superClass; ++ ++ public FinalSupertypeFix(@NotNull JetClass childClass) { ++ super(childClass); ++ this.childClass = childClass; ++ } ++ ++ @Override ++ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { ++ if (!super.isAvailable(project, editor, file)) { ++ return false; ++ } ++ ++ BindingContext context = KotlinCacheManager.getInstance(project).getDeclarationsFromProject(project).getBindingContext(); ++ ClassDescriptor childClassDescriptor = context.get(BindingContext.CLASS, childClass); ++ if (childClassDescriptor == null) { ++ return false; ++ } ++ for (JetType supertype: childClassDescriptor.getTypeConstructor().getSupertypes()) { ++ ClassDescriptor superClassDescriptor = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor(); ++ if (superClassDescriptor == null) { ++ continue; ++ } ++ PsiElement boundElement = BindingContextUtils.descriptorToDeclaration(context, superClassDescriptor); ++ if (boundElement instanceof JetClass) {","Why do you call it ""bound element""? +",2013-01-29 14:11:30 +28,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.ClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.JetClass; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lexer.JetKeywordToken; ++import org.jetbrains.jet.lexer.JetToken; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; ++ ++import static org.jetbrains.jet.lexer.JetTokens.FINAL_KEYWORD; ++import static org.jetbrains.jet.lexer.JetTokens.OPEN_KEYWORD; ++ ++public class FinalSupertypeFix extends JetIntentionAction { ++ private final JetClass childClass; ++ private JetClass superClass; ++ ++ public FinalSupertypeFix(@NotNull JetClass childClass) { ++ super(childClass); ++ this.childClass = childClass; ++ } ++ ++ @Override ++ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { ++ if (!super.isAvailable(project, editor, file)) { ++ return false; ++ } ++ ++ BindingContext context = KotlinCacheManager.getInstance(project).getDeclarationsFromProject(project).getBindingContext(); ++ ClassDescriptor childClassDescriptor = context.get(BindingContext.CLASS, childClass); ++ if (childClassDescriptor == null) { ++ return false; ++ } ++ for (JetType supertype: childClassDescriptor.getTypeConstructor().getSupertypes()) { ++ ClassDescriptor superClassDescriptor = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor(); ++ if (superClassDescriptor == null) { ++ continue; ++ } ++ PsiElement boundElement = BindingContextUtils.descriptorToDeclaration(context, superClassDescriptor); ++ if (boundElement instanceof JetClass) { ++ superClass = (JetClass) boundElement; ++ if (!superClass.isTrait() && !superClass.isEnum() && superClass.getContainingFile().isWritable()) { ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""add.supertype.modifier"", ""open""); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""add.supertype.modifier.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert superClass != null; ++ JetToken[] modifiersThanCanBeReplaced = new JetKeywordToken[] { FINAL_KEYWORD }; ++ superClass.replace(AddModifierFix.addModifier(superClass, OPEN_KEYWORD, modifiersThanCanBeReplaced, project, false)); ++ } ++ ++ @Nullable","Why is this method nullable? +",2013-01-29 14:13:59 +168,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++","Please declare all variables exactly before they are needed. It's usually a bad idea to declare all variables at once and then write the whole logic. A reader might think that the following behavior somehow depends on values of all these variables, while in reality your code should look more like: if doesn't have declared param types, return true; **else** if doesn't have declared return type, return true; **else** and so on. That's a lot easier to grasp, since you don't have to carry a lot of context while reading the code +",2014-04-09 16:03:44 +155,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral())","There's an inspection here saying that you should use `[]` instead of `get` +",2014-04-09 15:27:00 +157,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType()","There are warnings saying that `!!` is useless on `func`, since it's been already checked to be non-null. + +Also these variables don't add much to the readability, it may be a good idea to inline them +",2014-04-09 15:28:01 +158,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ ++ if (!hasDeclaredReturnType && expectedReturnType != null) return true ++ if (!hasDeclaredReceiverType && expectedReceiverType != null) return true ++ if (!hasDeclaredParamsType && func!!.getValueParameters() != null) return true","There's a warning saying that `getValueParameters` never returns null. Maybe you meant to check if it's non-empty? +",2014-04-09 15:28:26 +161,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ ++ if (!hasDeclaredReturnType && expectedReturnType != null) return true ++ if (!hasDeclaredReceiverType && expectedReceiverType != null) return true ++ if (!hasDeclaredParamsType && func!!.getValueParameters() != null) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val params = element.getFunctionLiteral().getValueParameterList()","You call `element.getFunctionLiteral()` **a lot** in this function. Why not extract it to a named variable? +",2014-04-09 15:39:27 +156,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ ++ if (!hasDeclaredReturnType && expectedReturnType != null) return true ++ if (!hasDeclaredReceiverType && expectedReceiverType != null) return true ++ if (!hasDeclaredParamsType && func!!.getValueParameters() != null) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val params = element.getFunctionLiteral().getValueParameterList() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral())!!","Ditto (`[]` instead of `get`) +",2014-04-09 15:27:22 +166,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ ++ if (!hasDeclaredReturnType && expectedReturnType != null) return true ++ if (!hasDeclaredReceiverType && expectedReceiverType != null) return true ++ if (!hasDeclaredParamsType && func!!.getValueParameters() != null) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val params = element.getFunctionLiteral().getValueParameterList() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral())!! ++ val valueParameters = func!!.getValueParameters() ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType()","Again, please declare all variables exactly before they are needed. In this function, `expectedReturnType` is only needed in Step 2, so declare it there. `expectedReceiverType` is only needed in Step 3, and so on +",2014-04-09 15:53:33 +160,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ ++ if (!hasDeclaredReturnType && expectedReturnType != null) return true ++ if (!hasDeclaredReceiverType && expectedReceiverType != null) return true ++ if (!hasDeclaredParamsType && func!!.getValueParameters() != null) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val params = element.getFunctionLiteral().getValueParameterList() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral())!! ++ val valueParameters = func!!.getValueParameters() ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ val parameterString = StringUtil.join(valueParameters, ++ {(descriptor: ValueParameterDescriptor?): String -> ++ """" + descriptor!!.getName() + ++ "": "" + DescriptorRenderer.TEXT.renderType(descriptor!!.getType())","There's a warning here about a useless `!!`: you've already asserted that `descriptor` is non-null on the previous line +",2014-04-09 15:37:48 +165,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ ++ if (!hasDeclaredReturnType && expectedReturnType != null) return true ++ if (!hasDeclaredReceiverType && expectedReceiverType != null) return true ++ if (!hasDeclaredParamsType && func!!.getValueParameters() != null) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val params = element.getFunctionLiteral().getValueParameterList() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral())!! ++ val valueParameters = func!!.getValueParameters() ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ val parameterString = StringUtil.join(valueParameters, ++ {(descriptor: ValueParameterDescriptor?): String -> ++ """" + descriptor!!.getName() + ++ "": "" + DescriptorRenderer.TEXT.renderType(descriptor!!.getType()) ++ }, ++ "", ""); ++ ++ // Step 1: make the parameters types explicit ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), ""("" + parameterString + "")"")","A nicer way would be to use `makeString`, which allows to pass a prefix and a postfix: +`val parameterString = valueParameters.map { ... }.makeString("", "", ""("", "")"")` +",2014-04-09 15:53:16 +159,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import com.intellij.openapi.util.text.StringUtil ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral()) ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ ++ if (!hasDeclaredReturnType && expectedReturnType != null) return true ++ if (!hasDeclaredReceiverType && expectedReceiverType != null) return true ++ if (!hasDeclaredParamsType && func!!.getValueParameters() != null) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val params = element.getFunctionLiteral().getValueParameterList() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context.get(BindingContext.FUNCTION, element.getFunctionLiteral())!! ++ val valueParameters = func!!.getValueParameters() ++ val expectedReturnType = func!!.getReturnType() ++ val expectedReceiverType = func!!.getReceiverParameter()?.getType() ++ val parameterString = StringUtil.join(valueParameters, ++ {(descriptor: ValueParameterDescriptor?): String -> ++ """" + descriptor!!.getName() + ++ "": "" + DescriptorRenderer.TEXT.renderType(descriptor!!.getType()) ++ }, ++ "", ""); ++ ++ // Step 1: make the parameters types explicit ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), ""("" + parameterString + "")"") ++ if (params != null) { ++ params.replace(newParameterList) ++ } ++ else { ++ val openBraceElement = element.getFunctionLiteral().getOpenBraceNode().getPsi() ++ val nextSibling = openBraceElement?.getNextSibling() ++ val whitespaceToAdd = (if (nextSibling is PsiWhiteSpace && nextSibling?.getText()?.contains(""\n"")?: false) ++ nextSibling?.copy()","There's a warning here and on the previous line about a useless `?:` +",2014-04-09 15:37:15 +794,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import com.intellij.psi.CommonClassNames ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.ElementKind ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++import javax.lang.model.element.VariableElement ++import javax.lang.model.type.NoType ++import javax.lang.model.type.TypeKind ++ ++class SymbolBasedClass(element: T,",Looks like generic parameter `T` can de dropped here and `element` could just have the type `TypeElement`,2017-04-25 11:08:53 +792,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import com.intellij.psi.CommonClassNames ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.ElementKind ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++import javax.lang.model.element.VariableElement ++import javax.lang.model.type.NoType ++import javax.lang.model.type.TypeKind ++ ++class SymbolBasedClass(element: T, ++ javac: JavacWrapper) : SymbolBasedClassifier(element, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(element.simpleName.toString())","There's no point in calling `safeIdentifier` on a non-null string, it's the same as simply `Name.identifier`. Maybe you meant to handle the case of anonymous classes? The docs say an empty string will be returned in that case.",2017-04-25 11:05:28 +795,"@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import com.intellij.psi.CommonClassNames ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.ElementKind ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++import javax.lang.model.element.VariableElement ++import javax.lang.model.type.NoType ++import javax.lang.model.type.TypeKind ++ ++class SymbolBasedClass(element: T, ++ javac: JavacWrapper) : SymbolBasedClassifier(element, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(element.simpleName.toString()) ++ ++ override val isAbstract ++ get() = element.isAbstract ++ ++ override val isStatic ++ get() = element.isStatic ++ ++ override val isFinal ++ get() = element.isFinal ++ ++ override val visibility ++ get() = element.getVisibility() ++ ++ override val typeParameters ++ get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) } ++ ++ override val fqName ++ get() = FqName(element.qualifiedName.toString()) ++ ++ override val supertypes","To be honest, I prefer properties and functions with explicit return type, unless omitting it makes code substantially more readable, which is not the case here, I think (I mean not only this file, but all files added in these commits).",2017-04-25 11:37:42 +965,"@@ -0,0 +1,11 @@ ++// !DIAGNOSTICS: -INVISIBLE_MEMBER -INVISIBLE_REFERENCE -UNUSED_PARAMETER ++// !LANGUAGE: +CalledInPlaceEffect ++ ++import kotlin.internal.* ++ ++inline fun myRun(@CalledInPlace(InvocationCount.EXACTLY_ONCE) block: () -> Unit) = block() ++ ++fun throwInLambda(): Int { ++ val x = myRun { throw java.lang.IllegalArgumentException() } ++ return x","Unclear place. First, why `TYPE_MISMATCH`? In this context, `x` should probably have `Nothing` type. Second, `UNREACHABLE_CODE` is expected here. Third, I don't quite understand why it appears after introduction of language features (the last but one commit).",2017-08-15 15:43:47 +233,"@@ -0,0 +1,11 @@ ++// WITH_RUNTIME ++// IS_APPLICABLE: FALSE ++import java.util.LinkedList ++ ++fun Int.withIndices(): List> = LinkedList>() ++ ++fun foo(s: Int) { ++ for ((index, a) in s.withIndices()) { ++ ++ } ++}","Also please rename this test +",2014-05-12 13:12:46 +206,"@@ -0,0 +1,110 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++import org.jetbrains.jet.lang.psi.JetCallableReferenceExpression ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++import kotlin.properties.Delegates ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.plugin.intentions.branchedTransformations.extractExpressionIfSingle ++import org.jetbrains.jet.lang.psi.JetThrowExpression ++import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall ++import org.jetbrains.jet.lang.descriptors.CallableDescriptor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import com.intellij.psi.PsiElement ++import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetUserType ++ ++public class ConvertIfWithThrowToAssertIntention : JetSelfTargetingIntention( ++ ""convert.if.with.throw.to.assert"", javaClass()) { ++ ++ private var resolvedCall: ResolvedCall by Delegates.notNull() ++ private var param: ResolvedValueArgument by Delegates.notNull() ++ ++ override fun isApplicableTo(element: JetIfExpression): Boolean { ++ if (element.getElse() != null) return false ++ ++ val thenExpr = element.getThen()?.extractExpressionIfSingle() ++ if (thenExpr !is JetThrowExpression) return false ++ ++ val thrownExpr = getSelector(thenExpr.getThrownExpression()) ++ if (thrownExpr !is JetCallExpression) return false ++ ++ if (thrownExpr.getCalleeExpression()?.getText() != ""AssertionError"") return false ++ ++ val context = AnalyzerFacadeWithCache.getContextForElement(thrownExpr) ++ val nullableResolvedCall = context[BindingContext.RESOLVED_CALL, thrownExpr.getCalleeExpression()] ++ if (nullableResolvedCall == null) return false ++ resolvedCall = nullableResolvedCall ++ ++ val paramAmount = resolvedCall.getValueArguments().size ++ if (paramAmount != 1) return false ++ ++ val paramDescriptor = resolvedCall.getResultingDescriptor().getValueParameters()[0] ++ param = resolvedCall.getValueArguments()[paramDescriptor]!! ++ if (param.toString() == ""null"") return false ++ ++ return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() == ""java.lang.AssertionError."" ++ } ++ ++ private fun getSelector(element: JetExpression?): JetExpression? { ++ if (element is JetDotQualifiedExpression) { ++ return element.getSelectorExpression() ++ } ++ return element ++ } ++ ++ override fun applyTo(element: JetIfExpression, editor: Editor) { ++ val condition = element.getCondition() ++ if (condition == null) return ++ ++ val negatedCondition = JetPsiFactory.createExpression(element.getProject(), ""!true"") as JetPrefixExpression ++ negatedCondition.getBaseExpression()!!.replace(condition) ++ condition.replace(negatedCondition) ++ ++ val newCondition = element.getCondition() as JetPrefixExpression ++ val simplifier = SimplifyNegatedBinaryExpressionIntention() ++ if (simplifier.isApplicableTo(newCondition)) { ++ simplifier.applyTo(newCondition, editor) ++ } ++ ++ val assertText = ""assert(${element.getCondition()?.getText()}, $param)"" ++ val assertExpr = JetPsiFactory.createExpression(element.getProject(), assertText) ++ ++ val newExpr = element.replace(assertExpr) as JetCallExpression ++ if (isCalResolvedToKotlinAssert(newExpr)) return","ShortenReferences was not working for ""kotlin.assert"" it would always process it back to the full ""kotlin.assert"", i tried debugging it for a couple of days but when i couldn't i figured this method should be just as good, I create the element with the short name ""assert"" and then get the resolved call, if it doesn't resolve to ""kotlin.assert"" i replace it with the dot qualified call +",2014-04-23 02:33:29 +685,"@@ -0,0 +1,111 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.android.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++import org.jetbrains.android.facet.AndroidFacet ++import org.jetbrains.kotlin.descriptors.ClassDescriptor ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors.SUPERTYPE_NOT_INITIALIZED ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction ++import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory ++import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.makeNotNullable ++import org.jetbrains.kotlin.types.typeUtil.supertypes ++ ++class KotlinAndroidViewConstructorFix(element: KtSuperTypeEntry) : KotlinQuickFixAction(element) { ++ ++ override fun getText() = ""Add Android View constructors using '@JvmOverloads'"" ++ override fun getFamilyName() = text ++ ++ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { ++ if (AndroidFacet.getInstance(file) == null) return false ++ return super.isAvailable(project, editor, file) ++ } ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val element = element ?: return ++ val ktClass = element.containingClass() ?: return ++ ++ val factory = KtPsiFactory(element) ++ ++ val newPrimaryConstructor = factory.createDeclarationByPattern( ++ ""class A constructor(\n $0, $1, $2\n)"", ++ factory.createParameter(""context: android.content.Context""), ++ factory.createParameter(""attrs: android.util.AttributeSet? = null""), ++ factory.createParameter(""defStyleAttr: Int = 0"") ++ ).primaryConstructor ?: return ++ ++ val primaryConstructor = ktClass.createPrimaryConstructorIfAbsent().replaced(newPrimaryConstructor) ++ primaryConstructor.valueParameterList?.let { ShortenReferences.DEFAULT.process(it) } ++ ++ primaryConstructor.addAnnotation(fqNameAnnotation, whiteSpaceText = "" "") ++ ++ element.replace(factory.createSuperTypeCallEntry(element.text + ""(context, attrs, defStyleAttr)"")) ++ } ++ ++ companion object Factory : KotlinSingleIntentionActionFactory() { ++ ++ private val fqNameAnnotation = FqName(""kotlin.jvm.JvmOverloads"") ++ ++ private val requiredConstructorParameterTypes = ++ listOf(""android.content.Context"", ""android.util.AttributeSet"", ""kotlin.Int"") ++ ++ override fun createAction(diagnostic: Diagnostic): IntentionAction? { ++ val superTypeEntry = SUPERTYPE_NOT_INITIALIZED.cast(diagnostic).psiElement ++ ++ val ktClass = superTypeEntry.containingClass() ?: return null ++ if (ktClass.primaryConstructor != null) return null ++ ++ val context = superTypeEntry.analyze() ++ val type = superTypeEntry.typeReference?.let { context[BindingContext.TYPE, it] } ?: return null ++ ++ if (!type.isAndroidView() && type.supertypes().none { it.isAndroidView() }) return null ++ ++ val names = type.constructorParameters() ?: return null ++ if (requiredConstructorParameterTypes !in names) return null ++ ++ return KotlinAndroidViewConstructorFix(superTypeEntry) ++ } ++ ++ private fun KotlinType.isAndroidView(): Boolean { ++ return constructor.declarationDescriptor?.fqNameUnsafe?.asString() == ""android.view.View"" ++ } ++ ++ private fun KotlinType.constructorParameters(): List>? { ++ val classDescriptor = constructor.declarationDescriptor as? ClassDescriptor ?: return null ++ return classDescriptor.constructors.map { ++ it.valueParameters.map { IdeDescriptorRenderers.SOURCE_CODE_NOT_NULL_TYPE_APPROXIMATION.renderType(it.type.makeNotNullable()) } ++ } ++ } ++ }","I suggest minor refactoring +```kotlin +private fun KotlinType.getFqNameAsString() = constructor.declarationDescriptor?.fqNameUnsafe?.asString() + +private fun KotlinType.isAndroidView() = getFqNameAsString() == ""android.view.View"" + +// and we can avoid IdeDescriptorRenderers +// ... + it.valueParameters.map { it.type.getFqNameAsString() } +// ... +} +``` +",2017-01-25 15:22:48 +93,"@@ -0,0 +1,115 @@ ++/* ++ * Copyright 2010-2014 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.intentions.attributeCallReplacements ++ ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.JetBundle ++import com.intellij.psi.PsiFile ++import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypesAndPredicate ++import com.intellij.openapi.project.Project ++import com.intellij.codeInsight.intention.impl.BaseIntentionAction ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public abstract class AttributeCallReplacementIntention(val name: String) : BaseIntentionAction() { ++ { ++ setText(getFamilyName()) ++ } ++ ++ protected class Replacement(val target: JetExpression, val text: String) ++ ++ private val elementType = javaClass() ++ ++ abstract protected fun isApplicableToCall(call: JetCallExpression) : Boolean ++ abstract protected fun makeReplacement(element: JetQualifiedExpression, call: JetCallExpression, receiver: JetExpression) : Replacement ++ ++ protected fun getTarget(editor: Editor, file: PsiFile): JetDotQualifiedExpression? { ++ val offset = editor.getCaretModel().getOffset() ++ return file.findElementAt(offset)?.getParentByTypesAndPredicate(false, elementType) { ++ element -> with (element.getSelectorExpression()) {","Is this kosher? +",2014-01-23 23:44:53 +94,"@@ -0,0 +1,115 @@ ++/* ++ * Copyright 2010-2014 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.intentions.attributeCallReplacements ++ ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.JetBundle ++import com.intellij.psi.PsiFile ++import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypesAndPredicate ++import com.intellij.openapi.project.Project ++import com.intellij.codeInsight.intention.impl.BaseIntentionAction ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public abstract class AttributeCallReplacementIntention(val name: String) : BaseIntentionAction() { ++ { ++ setText(getFamilyName()) ++ } ++ ++ protected class Replacement(val target: JetExpression, val text: String) ++ ++ private val elementType = javaClass() ++ ++ abstract protected fun isApplicableToCall(call: JetCallExpression) : Boolean ++ abstract protected fun makeReplacement(element: JetQualifiedExpression, call: JetCallExpression, receiver: JetExpression) : Replacement ++ ++ protected fun getTarget(editor: Editor, file: PsiFile): JetDotQualifiedExpression? { ++ val offset = editor.getCaretModel().getOffset() ++ return file.findElementAt(offset)?.getParentByTypesAndPredicate(false, elementType) { ++ element -> with (element.getSelectorExpression()) { ++ when (this) { ++ is JetCallExpression -> isApplicableToCall(this) ++ else -> false ++ } ++ } ++ } ++ } ++ ++ public override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ return with (getTarget(editor, file)) { ++ when(this) { ++ null -> false ++ else -> { ++ updateText(this, this.getSelectorExpression() as JetCallExpression, this.getReceiverExpression()) ++ true ++ } ++ } ++ } ++ } ++ ++ // Override this to manually specify the intention text. ++ protected open fun updateText(element: JetQualifiedExpression, call: JetCallExpression, receiver: JetExpression) { ++ val replacement = makeReplacement(element, call, receiver) ++ val before = replacement.target.getText() ++ val after = replacement.text ++ if (before != null) ++ setText(before, after) ++ } ++ ++ protected fun setText(before: String, after: String) { ++ setText(JetBundle.message(""replace.attribute.call"", before, after)) ++ } ++ ++ ++ public override fun getFamilyName() : String { ++ return JetBundle.message(""replace.attribute.call.family"", name) ++ } ++ ++ public override fun invoke(project: Project, editor: Editor, file: PsiFile): Unit { ++ val target = getTarget(editor, file) ++ assert(target != null, ""Intention is not applicable"") ++ target!! // It matches","There has to be a better way to do this. +",2014-01-23 23:46:15 +727,"@@ -0,0 +1,117 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.jvm.compiler ++ ++import com.intellij.openapi.Disposable ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles ++import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment ++import org.jetbrains.kotlin.config.JVMConfigurationKeys ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.renderer.* ++import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil ++import org.jetbrains.kotlin.test.ConfigurationKind ++import org.jetbrains.kotlin.test.KotlinTestUtils ++import org.jetbrains.kotlin.test.TestCaseWithTmpdir ++import org.jetbrains.kotlin.test.TestJdkKind ++import org.junit.Assert ++ ++import java.io.File ++import java.io.IOException ++import java.lang.annotation.Retention ++ ++import org.jetbrains.kotlin.test.KotlinTestUtils.* ++import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile ++ ++abstract class AbstractCompileJavaAgainstKotlinTest : TestCaseWithTmpdir() { ++ ++ @Throws(IOException::class) ++ protected fun doTest(ktFilePath: String) { ++ Assert.assertTrue(ktFilePath.endsWith("".kt"")) ++ val ktFile = File(ktFilePath) ++ val javaFile = File(ktFilePath.replaceFirst(""\\.kt$"".toRegex(), "".java"")) ++ ++ val javaErrorFile = File(ktFilePath.replaceFirst(""\\.kt$"".toRegex(), "".javaerr.txt"")) ++ ++ val useJavac = true","I'd make this a class property, set it into `false` for old tests and `true` for new tests.",2017-04-05 15:31:36 +731,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList()",Why?,2017-04-05 15:47:11 +732,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName }",What do you want to find in the empty list (see above)?,2017-04-05 15:47:30 +730,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract","Is it true for interfaces? They are abstract without a modifier. I'm not sure should we return `abstract = true` for them, but probably yes.",2017-04-05 15:46:09 +741,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic",Probably false if class is nested in interface (see JCField),2017-04-05 16:03:31 +740,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = tree.modifiers.visibility",Probably false if class is nested in interface (see JCField),2017-04-05 16:02:55 +736,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = tree.modifiers.visibility ++ ++ override val typeParameters ++ get() = tree.typeParameters.map { JCTypeParameter(it, TreePath(treePath, it), javac) } ++ ++ override val fqName = treePath.reversed() ++ .joinToString(separator = ""."") { ++ (it as? JCTree.JCCompilationUnit)?.packageName?.toString() ++ ?: (it as JCTree.JCClassDecl).name ++ } ++ .let(::FqName) ++ ++ override val supertypes ++ get() = arrayListOf().apply { ++ fun JCTree.mapToJavaClassifierType() = when { ++ this is JCTree.JCExpression -> JCClassifierType(this, TreePath(treePath, this), javac)",Don't quite understand this branch. Do you have some example?,2017-04-05 15:53:36 +733,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = tree.modifiers.visibility ++ ++ override val typeParameters ++ get() = tree.typeParameters.map { JCTypeParameter(it, TreePath(treePath, it), javac) } ++ ++ override val fqName = treePath.reversed() ++ .joinToString(separator = ""."") { ++ (it as? JCTree.JCCompilationUnit)?.packageName?.toString() ++ ?: (it as JCTree.JCClassDecl).name ++ } ++ .let(::FqName) ++ ++ override val supertypes ++ get() = arrayListOf().apply { ++ fun JCTree.mapToJavaClassifierType() = when { ++ this is JCTree.JCExpression -> JCClassifierType(this, TreePath(treePath, this), javac) ++ this is JCTree.JCTypeApply -> JCClassifierTypeWithTypeArgument(this, TreePath(treePath, this), javac) ++ else -> null ++ } ++ ++ tree.extending?.mapToJavaClassifierType()?.let(this::add) ++ tree.implementing?.map { it.mapToJavaClassifierType() }?.filterNotNull()?.let(this::addAll) ++ ++ if (find { it.canonicalText == CommonClassNames.JAVA_LANG_OBJECT } == null) { ++ javac.JAVA_LANG_OBJECT?.let { add(JavacClassifierType(it.element.asType(), javac)) }","Again, do we need it if super class is given explicitly?",2017-04-05 15:48:23 +734,"@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCClassifier(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations: Collection ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = tree.modifiers.visibility ++ ++ override val typeParameters ++ get() = tree.typeParameters.map { JCTypeParameter(it, TreePath(treePath, it), javac) } ++ ++ override val fqName = treePath.reversed() ++ .joinToString(separator = ""."") { ++ (it as? JCTree.JCCompilationUnit)?.packageName?.toString() ++ ?: (it as JCTree.JCClassDecl).name ++ } ++ .let(::FqName) ++ ++ override val supertypes ++ get() = arrayListOf().apply { ++ fun JCTree.mapToJavaClassifierType() = when { ++ this is JCTree.JCExpression -> JCClassifierType(this, TreePath(treePath, this), javac) ++ this is JCTree.JCTypeApply -> JCClassifierTypeWithTypeArgument(this, TreePath(treePath, this), javac) ++ else -> null ++ } ++ ++ tree.extending?.mapToJavaClassifierType()?.let(this::add) ++ tree.implementing?.map { it.mapToJavaClassifierType() }?.filterNotNull()?.let(this::addAll) ++ ++ if (find { it.canonicalText == CommonClassNames.JAVA_LANG_OBJECT } == null) { ++ javac.JAVA_LANG_OBJECT?.let { add(JavacClassifierType(it.element.asType(), javac)) } ++ } ++ } ++ ++ override val innerClasses ++ get() = tree.members ++ .filterIsInstance(JCTree.JCClassDecl::class.java) ++ .map { JCClass(it, TreePath(treePath, it), javac) } ++ ++ override val outerClass ++ get() = (treePath.parentPath.leaf as? JCTree.JCClassDecl)?.let { JCClass(it, treePath.parentPath, javac) } ++ ++ override val isInterface by lazy { tree.modifiers.flags and Flags.INTERFACE.toLong() != 0L }","Here you're using `by lazy` instead of `get`. Why here, and why just here?",2017-04-05 15:49:22 +764,"@@ -0,0 +1,12 @@ ++ ++ ++ ++ ++ ++",Not needed,2017-04-18 06:50:54 +541,"@@ -0,0 +1,12 @@ ++class A { ++ val a = """" ++ val b = """" ++} ++ ++fun box(): String { ++ val a = A::a.name ++ if (a != ""a"") return ""Fail $a"" ++ val b = A::`b`.name ++ if (b != ""b"") return ""Fail $b"" ++ return ""OK""","This test doesn't check that no classes were generated for the property reference. I don't think it's possible in a `box` test, please try a bytecode listing test instead (`compiler/testData/codegen/bytecodeListing`). + +Also please test constructors and functions +",2016-04-22 19:46:08 +185,"@@ -0,0 +1,12 @@ ++public class TestingUse { ++ fun test6(funcLitfunc: ((x: Int) -> Int) -> Boolean, innerfunc: (y: Int) -> Int): Unit { ++ val result = funcLitfunc(innerfunc) ++ var num = 0 ++ if (result == true) num = 1 ++ else num = 2","This is a nice test case, but is this code really needed to test your intention? I think it's just confusing... +",2014-04-16 19:00:48 +876,"@@ -0,0 +1,120 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.LocalQuickFix ++import com.intellij.codeInspection.ProblemDescriptor ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.intentions.branchedTransformations.unwrapBlockOrParenthesis ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++ ++class ConstantConditionIfInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitIfExpression(expression: KtIfExpression) { ++ super.visitIfExpression(expression) ++ ++ val condition = expression.condition ?: return ++ ++ val context = condition.analyze(BodyResolveMode.PARTIAL) ++ val constantValue = condition.constantBooleanValue(context) ?: return ++ ++ val fixes = mutableListOf() ++ ++ if (expression.branch(constantValue) != null) { ++ fixes += SimplifyFix(constantValue, expression.isUsedAsExpression(context)) ++ } ++ ++ if (!constantValue && expression.`else` == null) { ++ fixes += RemoveFix() ++ } ++ ++ holder.registerProblem(expression, ""Condition of 'if' expression is constant"", *fixes.toTypedArray()) ++ } ++ } ++ } ++ ++ private class SimplifyFix( ++ private val conditionValue: Boolean, ++ private val isUsedAsExpression: Boolean ++ ) : LocalQuickFix { ++ override fun getFamilyName() = ""Simplify expression"" ++ ++ override fun applyFix(project: Project, descriptor: ProblemDescriptor) { ++ val ifExpression = descriptor.psiElement as? KtIfExpression ?: return ++ val caretModel = ifExpression.findExistingEditor()?.caretModel ++ ++ val branch = ifExpression.branch(conditionValue)?.unwrapBlockOrParenthesis() ?: return ++ ++ val lastExpression = ++ if (branch !is KtBlockExpression) {",Probably with `when` it will be more readable,2017-06-29 12:51:34 +175,"@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ private var hasImplicitReturnType = false ++ private var hasImplicitReceiverType = false","Please don't store any information in mutable `var`s inside your intention: it might cause problems with concurrency. E.g. see what problems Gavin encountered in #411 +",2014-04-16 16:49:58 +176,"@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ private var hasImplicitReturnType = false ++ private var hasImplicitReceiverType = false ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) {","This can be simplified to `paramsTextRange != null && caretLocation in paramsTextRange` or `paramsTextRange?.contains(caretLocation) ?: false`, whichever you like the most +",2014-04-16 17:36:06 +181,"@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ private var hasImplicitReturnType = false ++ private var hasImplicitReceiverType = false ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) { ++ caretLocation in paramsTextRange ++ } ++ else false ++ ++ if (!(caretLocation == openBraceOffset + 1 || caretLocation == closeBraceOffset || caretIsInParams)) return false","Please convert this to `&&` by DeMorgan, it'll be more readable that way +",2014-04-16 18:25:42 +178,"@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ private var hasImplicitReturnType = false ++ private var hasImplicitReceiverType = false ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) { ++ caretLocation in paramsTextRange ++ } ++ else false ++ ++ if (!(caretLocation == openBraceOffset + 1 || caretLocation == closeBraceOffset || caretIsInParams)) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ hasImplicitReturnType = !element.hasDeclaredReturnType() ++ hasImplicitReceiverType = element.getFunctionLiteral().getReceiverTypeRef() == null ++ if (hasImplicitReturnType && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.any { it.getTypeReference() == null } || params.isEmpty()) return true","This is rather minor, but you should always strive to do simple checks first and complex checks later. It increases both readability and performance. Here `params.isEmpty()` is obviously very cheap compared to the other condition which involves looping over a collection +",2014-04-16 17:50:33 +177,"@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ private var hasImplicitReturnType = false ++ private var hasImplicitReceiverType = false ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) { ++ caretLocation in paramsTextRange ++ } ++ else false ++ ++ if (!(caretLocation == openBraceOffset + 1 || caretLocation == closeBraceOffset || caretIsInParams)) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ hasImplicitReturnType = !element.hasDeclaredReturnType() ++ hasImplicitReceiverType = element.getFunctionLiteral().getReceiverTypeRef() == null ++ if (hasImplicitReturnType && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.any { it.getTypeReference() == null } || params.isEmpty()) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, functionLiteral]!! ++ ++ // Step 1: make the parameters types explicit ++ val valueParameters = func.getValueParameters() ++ val parameterString = valueParameters.map({(descriptor: ValueParameterDescriptor?): String ->","Type of `descriptor` can be a non-null `ValueParameterDescriptor` here, because Kotlin sees Java generic types with non-null type arguments by default, so `valueParameters` is actually `List`, not `List` +",2014-04-16 17:48:39 +179,"@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ private var hasImplicitReturnType = false ++ private var hasImplicitReceiverType = false ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) { ++ caretLocation in paramsTextRange ++ } ++ else false ++ ++ if (!(caretLocation == openBraceOffset + 1 || caretLocation == closeBraceOffset || caretIsInParams)) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ hasImplicitReturnType = !element.hasDeclaredReturnType() ++ hasImplicitReceiverType = element.getFunctionLiteral().getReceiverTypeRef() == null ++ if (hasImplicitReturnType && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.any { it.getTypeReference() == null } || params.isEmpty()) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, functionLiteral]!! ++ ++ // Step 1: make the parameters types explicit ++ val valueParameters = func.getValueParameters() ++ val parameterString = valueParameters.map({(descriptor: ValueParameterDescriptor?): String -> ++ """" + descriptor!!.getName() + ++ "": "" + DescriptorRenderer.TEXT.renderType(descriptor.getType()) ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ val params = functionLiteral.getValueParameterList()","I think `params` should have been named `oldParameterList`, to oppose `newParameterList` +",2014-04-16 17:52:19 +180,"@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ private var hasImplicitReturnType = false ++ private var hasImplicitReceiverType = false ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) { ++ caretLocation in paramsTextRange ++ } ++ else false ++ ++ if (!(caretLocation == openBraceOffset + 1 || caretLocation == closeBraceOffset || caretIsInParams)) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ hasImplicitReturnType = !element.hasDeclaredReturnType() ++ hasImplicitReceiverType = element.getFunctionLiteral().getReceiverTypeRef() == null ++ if (hasImplicitReturnType && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.any { it.getTypeReference() == null } || params.isEmpty()) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, functionLiteral]!! ++ ++ // Step 1: make the parameters types explicit ++ val valueParameters = func.getValueParameters() ++ val parameterString = valueParameters.map({(descriptor: ValueParameterDescriptor?): String -> ++ """" + descriptor!!.getName() + ++ "": "" + DescriptorRenderer.TEXT.renderType(descriptor.getType()) ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ val params = functionLiteral.getValueParameterList() ++ if (params != null) { ++ params.replace(newParameterList) ++ } ++ else { ++ val openBraceElement = functionLiteral.getOpenBraceNode().getPsi() ++ val nextSibling = openBraceElement?.getNextSibling() ++ val whitespaceToAdd = (if (nextSibling is PsiWhiteSpace && nextSibling?.getText()?.contains(""\n"")?: false)","There's a warning on `?.` here :) If you're not sure whether or not your code has warnings, check the small box in IntelliJ's top-right corner, it should be green +",2014-04-16 17:53:51 +201,"@@ -0,0 +1,122 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ if (hasImplicitReturnType(element) && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType(element) && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.isEmpty() || params.any { it.getTypeReference() == null }) return true ++ ++ return false","Please collapse these two lines. `if (condition) return true; return false` can be simplified to `return condition` +",2014-04-22 22:33:06 +200,"@@ -0,0 +1,122 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ if (hasImplicitReturnType(element) && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType(element) && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.isEmpty() || params.any { it.getTypeReference() == null }) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, functionLiteral]!! ++ ++ // Step 1: make the parameters types explicit ++ val valueParameters = func.getValueParameters() ++ val parameterString = valueParameters.map({(descriptor: ValueParameterDescriptor): String ->","Ditto: I don't think types are needed here +",2014-04-22 22:31:08 +199,"@@ -0,0 +1,122 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ if (hasImplicitReturnType(element) && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType(element) && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.isEmpty() || params.any { it.getTypeReference() == null }) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, functionLiteral]!! ++ ++ // Step 1: make the parameters types explicit ++ val valueParameters = func.getValueParameters() ++ val parameterString = valueParameters.map({(descriptor: ValueParameterDescriptor): String -> ++ """" + descriptor.getName() + ++ "": "" + DescriptorRenderer.TEXT.renderType(descriptor.getType()) ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ val oldParameterList = functionLiteral.getValueParameterList() ++ if (oldParameterList != null) { ++ oldParameterList.replace(newParameterList) ++ } ++ else { ++ val openBraceElement = functionLiteral.getOpenBraceNode().getPsi() ++ val nextSibling = openBraceElement?.getNextSibling() ++ val whitespaceToAdd = (if (nextSibling is PsiWhiteSpace && nextSibling.getText()?.contains(""\n"")?: false)","I couldn't find tests on this code, am I missing something? It looks kind of complex +",2014-04-22 22:30:41 +197,"@@ -0,0 +1,122 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor ++import org.jetbrains.jet.renderer.DescriptorRenderer ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++ ++public class MakeTypeExplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.explicit.in.lambda"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, element.getFunctionLiteral()] ++ if (func == null || ErrorUtils.containsErrorType(func)) return false ++ ++ if (hasImplicitReturnType(element) && func.getReturnType() != null) return true ++ if (hasImplicitReceiverType(element) && func.getReceiverParameter()?.getType() != null) return true ++ ++ val params = element.getValueParameters() ++ if (params.isEmpty() || params.any { it.getTypeReference() == null }) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val func = context[BindingContext.FUNCTION, functionLiteral]!! ++ ++ // Step 1: make the parameters types explicit ++ val valueParameters = func.getValueParameters() ++ val parameterString = valueParameters.map({(descriptor: ValueParameterDescriptor): String -> ++ """" + descriptor.getName() + ++ "": "" + DescriptorRenderer.TEXT.renderType(descriptor.getType()) ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ val oldParameterList = functionLiteral.getValueParameterList() ++ if (oldParameterList != null) { ++ oldParameterList.replace(newParameterList) ++ } ++ else { ++ val openBraceElement = functionLiteral.getOpenBraceNode().getPsi() ++ val nextSibling = openBraceElement?.getNextSibling() ++ val whitespaceToAdd = (if (nextSibling is PsiWhiteSpace && nextSibling.getText()?.contains(""\n"")?: false) ++ nextSibling.copy() ++ else ++ null) ++ val whitespaceAndArrow = JetPsiFactory.createWhitespaceAndArrow(element.getProject()) ++ functionLiteral.addRangeAfter(whitespaceAndArrow.first, whitespaceAndArrow.second, openBraceElement) ++ functionLiteral.addAfter(newParameterList, openBraceElement) ++ if (whitespaceToAdd != null) { ++ functionLiteral.addAfter(whitespaceToAdd, openBraceElement) ++ } ++ } ++ ShortenReferences.process(element.getValueParameters()) ++ ++ ++ // Step 2: make the return type explicit ++ val expectedReturnType = func.getReturnType() ++ if (hasImplicitReturnType(element) && expectedReturnType != null) { ++ val paramList = functionLiteral.getValueParameterList() ++ val returnTypeColon = JetPsiFactory.createColon(element.getProject()) ++ val returnTypeExpr = JetPsiFactory.createType(element.getProject(), DescriptorRenderer.TEXT.renderType(expectedReturnType)) ++ ShortenReferences.process(returnTypeExpr) ++ functionLiteral.addAfter(returnTypeExpr, paramList) ++ functionLiteral.addAfter(returnTypeColon, paramList) ++ } ++ ++ // Step 3: make the receiver type explicit ++ val expectedReceiverType = func.getReceiverParameter()?.getType() ++ if (hasImplicitReceiverType(element) && expectedReceiverType != null) { ++ val receiverTypeString = DescriptorRenderer.TEXT.renderType(expectedReceiverType) ++ val paramListString = functionLiteral.getValueParameterList()?.getText() ++ val paramListWithReceiver = JetPsiFactory.createExpression(element.getProject(), receiverTypeString + ""."" + paramListString) ++ ShortenReferences.process(paramListWithReceiver) ++ functionLiteral.getValueParameterList()?.replace(paramListWithReceiver) ++ } ++ } ++ ++ fun hasImplicitReturnType(element: JetFunctionLiteralExpression): Boolean { ++ return !element.hasDeclaredReturnType() ++ } ++ ++ fun hasImplicitReceiverType(element: JetFunctionLiteralExpression): Boolean { ++ return element.getFunctionLiteral().getReceiverTypeRef() == null ++ }","The last 2 functions in this file should be `private` +",2014-04-22 22:25:42 +656,"@@ -0,0 +1,124 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++ ++class ConvertTwoComparisonsToRangeCheckIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, ""Convert to range check"") { ++ ++ private data class RangeExpressionData(val value: String, val min: String, val max: String) ++ ++ override fun isApplicableTo(condition: KtBinaryExpression) = generateRangeExpressionData(condition) != null ++ ++ override fun applyTo(condition: KtBinaryExpression, editor: Editor?) { ++ val rangeData = generateRangeExpressionData(condition) ?: return ++ condition.replace(KtPsiFactory(condition).createExpressionByPattern(""$0 in $1..$2"", rangeData.value, rangeData.min, rangeData.max)) ++ } ++ ++ private fun generateRangeExpressionData(condition: KtBinaryExpression): RangeExpressionData? { ++ if (condition.operationToken != KtTokens.ANDAND) return null ++ val firstCondition = condition.left as? KtBinaryExpression ?: return null ++ val secondCondition = condition.right as? KtBinaryExpression ?: return null ++ val firstOpToken = firstCondition.operationToken ++ val secondOpToken = secondCondition.operationToken ++ val firstLeft = firstCondition.left ?: return null ++ val firstRight = firstCondition.right ?: return null ++ val secondLeft = secondCondition.left ?: return null ++ val secondRight = secondCondition.right ?: return null ++ ++ return when (firstOpToken) {","This `when` is written in a very straight-forward way. Please, think a bit how to make it shorter. All branches are very like one another.",2016-12-13 10:28:53 +658,"@@ -0,0 +1,124 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++ ++class ConvertTwoComparisonsToRangeCheckIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, ""Convert to range check"") { ++ ++ private data class RangeExpressionData(val value: String, val min: String, val max: String) ++ ++ override fun isApplicableTo(condition: KtBinaryExpression) = generateRangeExpressionData(condition) != null ++ ++ override fun applyTo(condition: KtBinaryExpression, editor: Editor?) { ++ val rangeData = generateRangeExpressionData(condition) ?: return ++ condition.replace(KtPsiFactory(condition).createExpressionByPattern(""$0 in $1..$2"", rangeData.value, rangeData.min, rangeData.max)) ++ } ++ ++ private fun generateRangeExpressionData(condition: KtBinaryExpression): RangeExpressionData? { ++ if (condition.operationToken != KtTokens.ANDAND) return null ++ val firstCondition = condition.left as? KtBinaryExpression ?: return null ++ val secondCondition = condition.right as? KtBinaryExpression ?: return null ++ val firstOpToken = firstCondition.operationToken ++ val secondOpToken = secondCondition.operationToken ++ val firstLeft = firstCondition.left ?: return null ++ val firstRight = firstCondition.right ?: return null ++ val secondLeft = secondCondition.left ?: return null ++ val secondRight = secondCondition.right ?: return null ++ ++ return when (firstOpToken) { ++ KtTokens.GTEQ, KtTokens.GT -> { ++ when (secondOpToken) { ++ KtTokens.GTEQ, KtTokens.GT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstLeft, firstRight, secondLeft, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstRight, secondRight, firstLeft, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ else -> null ++ } ++ KtTokens.LTEQ, KtTokens.LT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstLeft, firstRight, secondRight, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstRight, secondLeft, firstLeft, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ else -> null ++ } ++ else -> null ++ } ++ } ++ KtTokens.LTEQ, KtTokens.LT -> { ++ when (secondOpToken) { ++ KtTokens.GTEQ, KtTokens.GT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstLeft, secondRight, firstRight, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstRight, firstLeft, secondLeft, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ else -> null ++ } ++ KtTokens.LTEQ, KtTokens.LT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstLeft, secondLeft, firstRight, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstRight, firstLeft, secondRight, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ else -> null ++ } ++ else -> null ++ } ++ } ++ else -> null ++ } ++ } ++ ++ private fun generateRangeExpressionData(value: KtExpression, min: KtExpression, max: KtExpression, minDecrementByOne: Boolean = false, maxDecrementByOne: Boolean = false): RangeExpressionData? { ++ if (minDecrementByOne || maxDecrementByOne) { ++ val type = value.getType(value.analyze()) ?: return null ++ if (!KotlinBuiltIns.isInt(type) && !KotlinBuiltIns.isLong(type) && !KotlinBuiltIns.isShort(type) && !KotlinBuiltIns.isChar(type)) return null ++ } ++ ++ val minText = if (minDecrementByOne) min.getDecrementByOneString() else min.text ++ val maxText = if (maxDecrementByOne) max.getDecrementByOneString() else max.text ++ return RangeExpressionData(value.text, minText ?: return null, maxText ?: return null) ++ } ++ ++ private fun KtExpression.getDecrementByOneString(): String? { ++ val type = getType(analyze()) ?: return null ++ ++ when (this) { ++ is KtConstantExpression -> { ++ val number: Number = when { ++ KotlinBuiltIns.isInt(type) -> text.toInt() - 1 ++ KotlinBuiltIns.isLong(type) -> { ++ val text = text ++ val longText = if (text.endsWith(""l"") || text.endsWith(""L"")) text.substring(0, text.length - 1) else text ++ longText.toLong() - 1 ++ } ++ KotlinBuiltIns.isShort(type) -> java.lang.Short.parseShort(text) - 1 ++ KotlinBuiltIns.isChar(type) -> text[0].toInt() - 1","I think it is better to replace character with character, either explicit e.g. `'z' - 1` or implicit `'y'`",2016-12-13 10:34:59 +657,"@@ -0,0 +1,124 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++ ++class ConvertTwoComparisonsToRangeCheckIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, ""Convert to range check"") { ++ ++ private data class RangeExpressionData(val value: String, val min: String, val max: String) ++ ++ override fun isApplicableTo(condition: KtBinaryExpression) = generateRangeExpressionData(condition) != null ++ ++ override fun applyTo(condition: KtBinaryExpression, editor: Editor?) { ++ val rangeData = generateRangeExpressionData(condition) ?: return ++ condition.replace(KtPsiFactory(condition).createExpressionByPattern(""$0 in $1..$2"", rangeData.value, rangeData.min, rangeData.max)) ++ } ++ ++ private fun generateRangeExpressionData(condition: KtBinaryExpression): RangeExpressionData? { ++ if (condition.operationToken != KtTokens.ANDAND) return null ++ val firstCondition = condition.left as? KtBinaryExpression ?: return null ++ val secondCondition = condition.right as? KtBinaryExpression ?: return null ++ val firstOpToken = firstCondition.operationToken ++ val secondOpToken = secondCondition.operationToken ++ val firstLeft = firstCondition.left ?: return null ++ val firstRight = firstCondition.right ?: return null ++ val secondLeft = secondCondition.left ?: return null ++ val secondRight = secondCondition.right ?: return null ++ ++ return when (firstOpToken) { ++ KtTokens.GTEQ, KtTokens.GT -> { ++ when (secondOpToken) { ++ KtTokens.GTEQ, KtTokens.GT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstLeft, firstRight, secondLeft, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstRight, secondRight, firstLeft, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ else -> null ++ } ++ KtTokens.LTEQ, KtTokens.LT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstLeft, firstRight, secondRight, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstRight, secondLeft, firstLeft, minDecrementByOne = firstOpToken == KtTokens.GT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ else -> null ++ } ++ else -> null ++ } ++ } ++ KtTokens.LTEQ, KtTokens.LT -> { ++ when (secondOpToken) { ++ KtTokens.GTEQ, KtTokens.GT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstLeft, secondRight, firstRight, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstRight, firstLeft, secondLeft, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.GT) ++ else -> null ++ } ++ KtTokens.LTEQ, KtTokens.LT -> when { ++ firstLeft !is KtConstantExpression && firstLeft.evaluatesTo(secondRight) -> ++ generateRangeExpressionData(firstLeft, secondLeft, firstRight, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ firstRight !is KtConstantExpression && firstRight.evaluatesTo(secondLeft) -> ++ generateRangeExpressionData(firstRight, firstLeft, secondRight, minDecrementByOne = firstOpToken == KtTokens.LT, maxDecrementByOne = secondOpToken == KtTokens.LT) ++ else -> null ++ } ++ else -> null ++ } ++ } ++ else -> null ++ } ++ } ++ ++ private fun generateRangeExpressionData(value: KtExpression, min: KtExpression, max: KtExpression, minDecrementByOne: Boolean = false, maxDecrementByOne: Boolean = false): RangeExpressionData? { ++ if (minDecrementByOne || maxDecrementByOne) { ++ val type = value.getType(value.analyze()) ?: return null ++ if (!KotlinBuiltIns.isInt(type) && !KotlinBuiltIns.isLong(type) && !KotlinBuiltIns.isShort(type) && !KotlinBuiltIns.isChar(type)) return null ++ } ++ ++ val minText = if (minDecrementByOne) min.getDecrementByOneString() else min.text ++ val maxText = if (maxDecrementByOne) max.getDecrementByOneString() else max.text ++ return RangeExpressionData(value.text, minText ?: return null, maxText ?: return null) ++ } ++ ++ private fun KtExpression.getDecrementByOneString(): String? { ++ val type = getType(analyze()) ?: return null ++ ++ when (this) { ++ is KtConstantExpression -> { ++ val number: Number = when { ++ KotlinBuiltIns.isInt(type) -> text.toInt() - 1 ++ KotlinBuiltIns.isLong(type) -> { ++ val text = text ++ val longText = if (text.endsWith(""l"") || text.endsWith(""L"")) text.substring(0, text.length - 1) else text ++ longText.toLong() - 1 ++ } ++ KotlinBuiltIns.isShort(type) -> java.lang.Short.parseShort(text) - 1 ++ KotlinBuiltIns.isChar(type) -> text[0].toInt() - 1 ++ else -> return null ++ } ++ return number.toString() ++ } ++ else -> return ""($text - 1)""","This is very controversial. What if expression is a `String`, for example?",2016-12-13 10:33:10 +757,"@@ -0,0 +1,124 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : JCElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { JCAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic",What about interface member classes? (they're always static as I know),2017-04-11 10:22:16 +758,"@@ -0,0 +1,124 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.intellij.psi.CommonClassNames ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.JavacClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class JCClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : JCElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { JCAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = tree.modifiers.visibility",What about interface member classes? (they're always public as I know),2017-04-11 10:22:49 +680,"@@ -0,0 +1,126 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.android.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.* ++import com.intellij.psi.util.PsiTypesUtil ++import org.jetbrains.android.facet.AndroidFacet ++import org.jetbrains.kotlin.asJava.toLightClass ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors.SUPERTYPE_NOT_INITIALIZED ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction ++import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.supertypes ++ ++class KotlinAndroidViewConstructorFix(element: KtSuperTypeEntry) : KotlinQuickFixAction(element) { ++ ++ override fun getText() = ""Add Android View constructors using '@JvmOverloads'"" ++ override fun getFamilyName() = text ++ ++ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { ++ if (AndroidFacet.getInstance(file) == null) return false ++ return super.isAvailable(project, editor, file) ++ } ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val element = element ?: return ++ val ktClass = element.containingClass() ?: return ++ ++ val factory = KtPsiFactory(element) ++ ++ val newPrimaryConstructor = factory.createDeclarationByPattern( ++ ""class A constructor(\n $0, $1, $2\n)"", ++ factory.createParameter(""context: android.content.Context""), ++ factory.createParameter(""attrs: android.util.AttributeSet? = null""), ++ factory.createParameter(""defStyleAttr: Int = 0"") ++ ).primaryConstructor!!",i think `?: return` will be better,2017-01-25 12:41:42 +681,"@@ -0,0 +1,126 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.android.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.* ++import com.intellij.psi.util.PsiTypesUtil ++import org.jetbrains.android.facet.AndroidFacet ++import org.jetbrains.kotlin.asJava.toLightClass ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors.SUPERTYPE_NOT_INITIALIZED ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction ++import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.supertypes ++ ++class KotlinAndroidViewConstructorFix(element: KtSuperTypeEntry) : KotlinQuickFixAction(element) { ++ ++ override fun getText() = ""Add Android View constructors using '@JvmOverloads'"" ++ override fun getFamilyName() = text ++ ++ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { ++ if (AndroidFacet.getInstance(file) == null) return false ++ return super.isAvailable(project, editor, file) ++ } ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val element = element ?: return ++ val ktClass = element.containingClass() ?: return ++ ++ val factory = KtPsiFactory(element) ++ ++ val newPrimaryConstructor = factory.createDeclarationByPattern( ++ ""class A constructor(\n $0, $1, $2\n)"", ++ factory.createParameter(""context: android.content.Context""), ++ factory.createParameter(""attrs: android.util.AttributeSet? = null""), ++ factory.createParameter(""defStyleAttr: Int = 0"") ++ ).primaryConstructor!! ++ ++ val primaryConstructor = ktClass.createPrimaryConstructorIfAbsent().replaced(newPrimaryConstructor) ++ ShortenReferences.DEFAULT.process(primaryConstructor.valueParameterList!!)",`primaryConstructor.valueParameterList?.apply { ShortenReferences.DEFAULT.process(this) }`,2017-01-25 12:42:55 +682,"@@ -0,0 +1,126 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.android.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.* ++import com.intellij.psi.util.PsiTypesUtil ++import org.jetbrains.android.facet.AndroidFacet ++import org.jetbrains.kotlin.asJava.toLightClass ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors.SUPERTYPE_NOT_INITIALIZED ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction ++import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.supertypes ++ ++class KotlinAndroidViewConstructorFix(element: KtSuperTypeEntry) : KotlinQuickFixAction(element) { ++ ++ override fun getText() = ""Add Android View constructors using '@JvmOverloads'"" ++ override fun getFamilyName() = text ++ ++ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { ++ if (AndroidFacet.getInstance(file) == null) return false ++ return super.isAvailable(project, editor, file) ++ } ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val element = element ?: return ++ val ktClass = element.containingClass() ?: return ++ ++ val factory = KtPsiFactory(element) ++ ++ val newPrimaryConstructor = factory.createDeclarationByPattern( ++ ""class A constructor(\n $0, $1, $2\n)"", ++ factory.createParameter(""context: android.content.Context""), ++ factory.createParameter(""attrs: android.util.AttributeSet? = null""), ++ factory.createParameter(""defStyleAttr: Int = 0"") ++ ).primaryConstructor!! ++ ++ val primaryConstructor = ktClass.createPrimaryConstructorIfAbsent().replaced(newPrimaryConstructor) ++ ShortenReferences.DEFAULT.process(primaryConstructor.valueParameterList!!) ++ ++ primaryConstructor.addAnnotation(fqNameAnnotation, whiteSpaceText = "" "") ++ ++ element.replace(factory.createSuperTypeCallEntry(element.text + ""(context, attrs, defStyleAttr)"")) ++ } ++ ++ companion object Factory : KotlinSingleIntentionActionFactory() { ++ ++ private val fqNameAnnotation = FqName(""kotlin.jvm.JvmOverloads"") ++ ++ private val requireConstructorParameterTypes = listOf(","I think we may check only for a presence of the third one `""android.content.Context"", ""android.util.AttributeSet"", ""int""`, since we are using only it, if I understood correctly",2017-01-25 12:45:15 +683,"@@ -0,0 +1,126 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.android.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.* ++import com.intellij.psi.util.PsiTypesUtil ++import org.jetbrains.android.facet.AndroidFacet ++import org.jetbrains.kotlin.asJava.toLightClass ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors.SUPERTYPE_NOT_INITIALIZED ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction ++import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.supertypes ++ ++class KotlinAndroidViewConstructorFix(element: KtSuperTypeEntry) : KotlinQuickFixAction(element) { ++ ++ override fun getText() = ""Add Android View constructors using '@JvmOverloads'"" ++ override fun getFamilyName() = text ++ ++ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { ++ if (AndroidFacet.getInstance(file) == null) return false ++ return super.isAvailable(project, editor, file) ++ } ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val element = element ?: return ++ val ktClass = element.containingClass() ?: return ++ ++ val factory = KtPsiFactory(element) ++ ++ val newPrimaryConstructor = factory.createDeclarationByPattern( ++ ""class A constructor(\n $0, $1, $2\n)"", ++ factory.createParameter(""context: android.content.Context""), ++ factory.createParameter(""attrs: android.util.AttributeSet? = null""), ++ factory.createParameter(""defStyleAttr: Int = 0"") ++ ).primaryConstructor!! ++ ++ val primaryConstructor = ktClass.createPrimaryConstructorIfAbsent().replaced(newPrimaryConstructor) ++ ShortenReferences.DEFAULT.process(primaryConstructor.valueParameterList!!) ++ ++ primaryConstructor.addAnnotation(fqNameAnnotation, whiteSpaceText = "" "") ++ ++ element.replace(factory.createSuperTypeCallEntry(element.text + ""(context, attrs, defStyleAttr)"")) ++ } ++ ++ companion object Factory : KotlinSingleIntentionActionFactory() { ++ ++ private val fqNameAnnotation = FqName(""kotlin.jvm.JvmOverloads"") ++ ++ private val requireConstructorParameterTypes = listOf( ++ listOf(""android.content.Context""), ++ listOf(""android.content.Context"", ""android.util.AttributeSet""), ++ listOf(""android.content.Context"", ""android.util.AttributeSet"", ""int"") ++ ) ++ ++ override fun createAction(diagnostic: Diagnostic): IntentionAction? { ++ val superTypeEntry = SUPERTYPE_NOT_INITIALIZED.cast(diagnostic).psiElement ++ ++ val ktClass = superTypeEntry.containingClass() ?: return null ++ if (ktClass.primaryConstructor != null) return null ++ ++ val context = superTypeEntry.analyze() ++ val type = superTypeEntry.typeReference?.let { context[BindingContext.TYPE, it] } ?: return null ++ ++ if (!type.isAndroidView() && type.supertypes().none { it.isAndroidView() }) return null ++ ++ var declaration = type.getDeclaration() ++ ++ if (declaration is KtClass) { ++ declaration = declaration.toLightClass()","I think it could be implemented without light classes, they are pretty heavy and should be avoided if possible +Try to get everything you need from descriptor +```Kotlin +val classDescriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null +val constructorParameters = classDescriptor.constructors.forEach { + it.valueParameters... // some checking stuff +} +```",2017-01-25 12:47:17 +8,"@@ -0,0 +1,13 @@","What is this file? Is it for manual testing? +",2012-06-05 15:04:48 +787,"@@ -0,0 +1,132 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.jvm.compiler ++ ++import com.intellij.openapi.Disposable ++import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles ++import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment ++import org.jetbrains.kotlin.config.JVMConfigurationKeys ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.renderer.* ++import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil ++import org.jetbrains.kotlin.test.ConfigurationKind ++import org.jetbrains.kotlin.test.KotlinTestUtils ++import org.jetbrains.kotlin.test.TestCaseWithTmpdir ++import org.jetbrains.kotlin.test.TestJdkKind ++import org.junit.Assert ++ ++import java.io.File ++import java.io.IOException ++import java.lang.annotation.Retention ++ ++import org.jetbrains.kotlin.test.KotlinTestUtils.* ++import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile ++ ++abstract class AbstractCompileJavaAgainstKotlinTest : TestCaseWithTmpdir() { ++ ++ @Throws(IOException::class) ++ protected fun doTest(ktFilePath: String) { ++ Assert.assertTrue(ktFilePath.endsWith("".kt"")) ++ val ktFile = File(ktFilePath) ++ val javaFile = File(ktFilePath.replaceFirst(""\\.kt$"".toRegex(), "".java"")) ++ ++ val javaErrorFile = File(ktFilePath.replaceFirst(""\\.kt$"".toRegex(), "".javaerr.txt"")) ++ ++ val out = File(tmpdir, ""out"") ++ ++ val useJavac = this::class.java.name.contains(""WithJavac"")",This is too hacky. We normally use a bunch of protected methods to inject custom behavior in abstract test class,2017-04-25 09:59:13 +793,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString())","Ditto, replace with `Name.identifier`",2017-04-25 11:06:11 +820,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract","Note that there's a corner case of enums with abstract members, which are considered abstract in Java but do not require (and even prohibit) the `abstract` keyword. Please add a test and ensure that it works",2017-04-25 13:32:10 +821,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic",Also please add a test on a nested enum (enum is never inner in Java),2017-04-25 13:35:09 +823,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = (outerClass?.isInterface ?: false) || tree.modifiers.isStatic","Not sure if `isInterface` returns true for annotations, please check and call `isAnnotation` if needed (a test would be nice in any case)",2017-04-25 13:41:01 +824,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = (outerClass?.isInterface ?: false) || tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = if (outerClass?.isInterface ?: false) PUBLIC else tree.modifiers.visibility",Also test annotations in addition to interfaces here,2017-04-25 13:41:49 +825,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = (outerClass?.isInterface ?: false) || tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = if (outerClass?.isInterface ?: false) PUBLIC else tree.modifiers.visibility ++ ++ override val typeParameters ++ get() = tree.typeParameters.map { TreeBasedTypeParameter(it, TreePath(treePath, it), javac) } ++ ++ override val fqName = treePath.reversed() ++ .joinToString(separator = ""."") { ++ (it as? JCTree.JCCompilationUnit)?.packageName?.toString() ++ ?: (it as JCTree.JCClassDecl).name ++ } ++ .let(::FqName) ++ ++ override val supertypes",There's also an implicit supertype `java.lang.annotation.Annotation` for all annotations,2017-04-25 13:42:38 +822,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = (outerClass?.isInterface ?: false) || tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = if (outerClass?.isInterface ?: false) PUBLIC else tree.modifiers.visibility ++ ++ override val typeParameters ++ get() = tree.typeParameters.map { TreeBasedTypeParameter(it, TreePath(treePath, it), javac) } ++ ++ override val fqName = treePath.reversed() ++ .joinToString(separator = ""."") { ++ (it as? JCTree.JCCompilationUnit)?.packageName?.toString() ++ ?: (it as JCTree.JCClassDecl).name ++ } ++ .let(::FqName) ++ ++ override val supertypes ++ get() = arrayListOf().apply { ++ fun JCTree.mapToJavaClassifierType() = when { ++ this is JCTree.JCTypeApply -> TreeBasedClassifierTypeWithTypeArgument(this, TreePath(treePath, this), javac) ++ this is JCTree.JCExpression -> TreeBasedClassifierTypeWithoutTypeArgument(this, TreePath(treePath, this), javac) ++ else -> null ++ } ++ ++ if (isEnum) { ++ (javac.findClass(FqName(""java.lang.Enum"")) as? SymbolBasedClass<*>) ++ ?.let { SymbolBasedType.create(it.element.asType(), javac) as? JavaClassifierType } ++ ?.let { add(it) } ++ } ++ ++ tree.implementing?.map { it.mapToJavaClassifierType() }?.filterNotNull()?.let(this::addAll)",`map` + `filterNotNull` = `mapNotNull`,2017-04-25 13:39:08 +826,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = (outerClass?.isInterface ?: false) || tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = if (outerClass?.isInterface ?: false) PUBLIC else tree.modifiers.visibility ++ ++ override val typeParameters ++ get() = tree.typeParameters.map { TreeBasedTypeParameter(it, TreePath(treePath, it), javac) } ++ ++ override val fqName = treePath.reversed() ++ .joinToString(separator = ""."") { ++ (it as? JCTree.JCCompilationUnit)?.packageName?.toString() ++ ?: (it as JCTree.JCClassDecl).name ++ } ++ .let(::FqName) ++ ++ override val supertypes ++ get() = arrayListOf().apply { ++ fun JCTree.mapToJavaClassifierType() = when { ++ this is JCTree.JCTypeApply -> TreeBasedClassifierTypeWithTypeArgument(this, TreePath(treePath, this), javac) ++ this is JCTree.JCExpression -> TreeBasedClassifierTypeWithoutTypeArgument(this, TreePath(treePath, this), javac) ++ else -> null ++ } ++ ++ if (isEnum) { ++ (javac.findClass(FqName(""java.lang.Enum"")) as? SymbolBasedClass<*>) ++ ?.let { SymbolBasedType.create(it.element.asType(), javac) as? JavaClassifierType } ++ ?.let { add(it) } ++ } ++ ++ tree.implementing?.map { it.mapToJavaClassifierType() }?.filterNotNull()?.let(this::addAll) ++ tree.extending?.let { it.mapToJavaClassifierType()?.let(this::add) } ++ ++ if (isEmpty()) { ++ javac.JAVA_LANG_OBJECT?.let { add(SymbolBasedClassifierType(it.element.asType(), javac)) } ++ } ++ } ++ ++ val innerClasses by lazy {",Please also call `.associateBy { it.name }` to make this a map from name to class. This will allow `innerClassNames` and `findInnerClass` to work in O(1),2017-04-25 13:46:06 +827,"@@ -0,0 +1,134 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.tree.TreeInfo ++import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClassifierType ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedType ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedClass(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaClass { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.simpleName.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = (outerClass?.isInterface ?: false) || tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility ++ get() = if (outerClass?.isInterface ?: false) PUBLIC else tree.modifiers.visibility ++ ++ override val typeParameters ++ get() = tree.typeParameters.map { TreeBasedTypeParameter(it, TreePath(treePath, it), javac) } ++ ++ override val fqName = treePath.reversed() ++ .joinToString(separator = ""."") { ++ (it as? JCTree.JCCompilationUnit)?.packageName?.toString() ++ ?: (it as JCTree.JCClassDecl).name ++ } ++ .let(::FqName) ++ ++ override val supertypes ++ get() = arrayListOf().apply { ++ fun JCTree.mapToJavaClassifierType() = when { ++ this is JCTree.JCTypeApply -> TreeBasedClassifierTypeWithTypeArgument(this, TreePath(treePath, this), javac) ++ this is JCTree.JCExpression -> TreeBasedClassifierTypeWithoutTypeArgument(this, TreePath(treePath, this), javac) ++ else -> null ++ } ++ ++ if (isEnum) { ++ (javac.findClass(FqName(""java.lang.Enum"")) as? SymbolBasedClass<*>) ++ ?.let { SymbolBasedType.create(it.element.asType(), javac) as? JavaClassifierType } ++ ?.let { add(it) } ++ } ++ ++ tree.implementing?.map { it.mapToJavaClassifierType() }?.filterNotNull()?.let(this::addAll) ++ tree.extending?.let { it.mapToJavaClassifierType()?.let(this::add) } ++ ++ if (isEmpty()) { ++ javac.JAVA_LANG_OBJECT?.let { add(SymbolBasedClassifierType(it.element.asType(), javac)) } ++ } ++ } ++ ++ val innerClasses by lazy { ++ tree.members ++ .filterIsInstance(JCTree.JCClassDecl::class.java) ++ .map { TreeBasedClass(it, TreePath(treePath, it), javac) } ++ } ++ ++ override val outerClass by lazy { ++ (treePath.parentPath.leaf as? JCTree.JCClassDecl)?.let { TreeBasedClass(it, treePath.parentPath, javac) } ++ } ++ ++ override val isInterface ++ get() = tree.modifiers.flags and Flags.INTERFACE.toLong() != 0L ++ ++ override val isAnnotationType ++ get() = tree.modifiers.flags and Flags.ANNOTATION.toLong() != 0L ++ ++ override val isEnum ++ get() = tree.modifiers.flags and Flags.ENUM.toLong() != 0L ++ ++ override val lightClassOriginKind = null",`get() = null`,2017-04-25 13:46:35 +53,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ }","Five constructors for non-API constructor seems to be too much. Maybe provide default values manually on call sites? +",2013-04-26 11:40:10 +54,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0;","Use ArrayList instead of array. This won't take much extra memory, but will simplify code. +",2013-04-26 11:40:40 +55,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) {","I don't understand what this method does. +",2013-04-26 11:42:59 +56,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options","What does mean ""applied""? +",2013-04-26 11:43:15 +57,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()];","Use list, and `Collections.reverse()` afterwards. +",2013-04-26 11:43:41 +58,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution {","We already have class called `TypeSubstitution` in Kotlin codebase, so, this name is too confusing. +",2013-04-26 11:44:34 +59,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++","Make popup look the same as for Java, see screenshot: +![Screen Shot 2013-04-24 at 18 17 37](https://f.cloud.github.com/assets/145855/430367/d8c2a7be-ae66-11e2-8886-ee07159d98d6.png) +",2013-04-26 11:45:17 +60,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options);","Why not use TypeCandidate instances as list elements? This would make it possible to avoid having String → TypeCandidate map. +",2013-04-26 11:47:58 +61,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex();","Why not check `getSelectedValue()` for null, if we access it anyway? +",2013-04-26 11:48:23 +62,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) {","`doInvoke` is not a good name, because it doesn't explain how it differs from simple `invoke`. Rename it to `addFunctionToSelectedOwner` or something like that. +",2013-04-26 11:48:53 +63,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor);","It's class declaration, not type declaration. Please rename. +",2013-04-26 11:50:12 +64,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) {","Checking for null is redundant when checking for `instanceof`. +",2013-04-26 11:50:32 +65,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution();","This code relies on implementation details. What if actual type of `ownerClassDescriptor` is `LazyClassDescriptor`? Replace it with `receiverType.getMemberScope()` +",2013-04-26 11:51:51 +66,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) {","`project` parameter is redundant, see above. +",2013-04-26 11:52:20 +67,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func);","Return immediately to avoid reassignment. +",2013-04-26 11:52:53 +68,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace);","Return immediately to avoid reassignment. +",2013-04-26 11:52:59 +69,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace); ++ } ++ ++ return func; ++ } ++ ++ private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) { ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // build templates ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument()); ++ ++ CaretModel caretModel = containingFileEditor.getCaretModel(); ++ caretModel.moveToOffset(containingFile.getNode().getStartOffset()); ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile); ++ final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); ++ final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); ++ ++ // add a segment for the parameter list ++ // Note: because TemplateBuilderImpl does not have a replaceElement overload that takes in both a TextRange and alwaysStopAt, we ++ // need to create the segment first and then hack the Expression into the template later. We use this template to update the type ++ // parameter list as the user makes selections in the parameter types, and we need alwaysStopAt to be false so the user can't tab to ++ // it. ++ TypeParameterListExpression expression = setupTypeParameterListTemplate(builder, func); ++ ++ // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it ++ final TemplateImpl template = (TemplateImpl) builder.buildInlineTemplate(); ++ ArrayList variables = template.getVariables(); ++ for (int i = 0; i < parameters.size(); i++) { ++ Collections.swap(variables, i * 2, i * 2 + 1); ++ } ++ ++ // fix up the template to include the expression for the type parameter list ++ variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); ++ ++ // run the template ++ TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template _, boolean brokenOff) {","Don't use such names, please. Even if parameter is not used. +",2013-04-26 11:54:36 +70,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace); ++ } ++ ++ return func; ++ } ++ ++ private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) { ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // build templates ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument()); ++ ++ CaretModel caretModel = containingFileEditor.getCaretModel(); ++ caretModel.moveToOffset(containingFile.getNode().getStartOffset()); ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile); ++ final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); ++ final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); ++ ++ // add a segment for the parameter list ++ // Note: because TemplateBuilderImpl does not have a replaceElement overload that takes in both a TextRange and alwaysStopAt, we ++ // need to create the segment first and then hack the Expression into the template later. We use this template to update the type ++ // parameter list as the user makes selections in the parameter types, and we need alwaysStopAt to be false so the user can't tab to ++ // it. ++ TypeParameterListExpression expression = setupTypeParameterListTemplate(builder, func); ++ ++ // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it ++ final TemplateImpl template = (TemplateImpl) builder.buildInlineTemplate(); ++ ArrayList variables = template.getVariables(); ++ for (int i = 0; i < parameters.size(); i++) { ++ Collections.swap(variables, i * 2, i * 2 + 1); ++ } ++ ++ // fix up the template to include the expression for the type parameter list ++ variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); ++ ++ // run the template ++ TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template _, boolean brokenOff) { ++ // file templates ++ int offset = template.getSegmentOffset(0); ++ final JetNamedFunction func = PsiTreeUtil.findElementOfClassAtOffset(containingFile, offset, JetNamedFunction.class, false); ++ assert func != null; ++ final List typeRefsToShorten = new ArrayList(); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ // file templates ++ setupFunctionBody(project, func); ++ ++ // change short type names to fully qualified ones (to be shortened below) ++ setupTypeReferencesForShortening(project, func, typeRefsToShorten, parameterTypeExpressions, returnTypeExpression); ++ } ++ }); ++ ++ ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten); ++ } ++ }); ++ } ++ ++ private Map getTypeParameterRenames(JetScope scope) { ++ TypeParameterDescriptor[] receiverTypeParametersNotInScope = selectedReceiverType.getTypeParameters(); ++ Set allTypeParametersNotInScope = new LinkedHashSet(); ++ allTypeParametersNotInScope.addAll(Arrays.asList(receiverTypeParametersNotInScope)); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(parameterTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ if (!isUnit) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(returnTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ List typeParameters = new ArrayList(allTypeParametersNotInScope); ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames.add(getNextAvailableName(typeParameter.getName().getName(), typeParameterNames, scope)); ++ } ++ assert typeParameters.size() == typeParameterNames.size(); ++ Map typeParameterNameMap = new HashMap(); ++ for (int i = 0; i < typeParameters.size(); i++) { ++ typeParameterNameMap.put(typeParameters.get(i), typeParameterNames.get(i)); ++ } ++ ++ return typeParameterNameMap; ++ } ++ ++ private void setupTypeReferencesForShortening( ++ @NotNull Project project, ++ @NotNull JetNamedFunction func, ++ @NotNull List typeRefsToShorten, ++ @NotNull TypeExpression[] parameterTypeExpressions, ++ @Nullable TypeExpression returnTypeExpression ++ ) { ++ if (isExtension) { ++ JetTypeReference receiverTypeRef = ++ JetPsiFactory.createType(project, renderTypeLong(selectedReceiverType.getType(), typeParameterNameMap)); ++ replaceWithLongerName(project, receiverTypeRef, selectedReceiverType.getType()); ++ ++ receiverTypeRef = func.getReceiverTypeRef(); ++ if (receiverTypeRef != null) { ++ typeRefsToShorten.add(receiverTypeRef); ++ } ++ } ++ ++ if (!isUnit) { ++ assert returnTypeExpression != null; ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ JetType returnType = returnTypeExpression.getTypeFromSelection(returnTypeRef.getText()); ++ if (returnType != null) { // user selected a given type ++ replaceWithLongerName(project, returnTypeRef, returnType); ++ returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ typeRefsToShorten.add(returnTypeRef); ++ } ++ } ++ } ++ ++ List valueParameters = func.getValueParameters(); ++ List parameterIndicesToShorten = new ArrayList(); ++ assert valueParameters.size() == parameterTypeExpressions.length; ++ for (int i = 0; i < valueParameters.size(); i++) { ++ JetParameter parameter = valueParameters.get(i); ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ JetType parameterType = parameterTypeExpressions[i].getTypeFromSelection(parameterTypeRef.getText()); ++ if (parameterType != null) { ++ replaceWithLongerName(project, parameterTypeRef, parameterType); ++ parameterIndicesToShorten.add(i); ++ } ++ } ++ } ++ valueParameters = func.getValueParameters(); ++ for (int i : parameterIndicesToShorten) { ++ JetTypeReference parameterTypeRef = valueParameters.get(i).getTypeReference(); ++ if (parameterTypeRef != null) { ++ typeRefsToShorten.add(parameterTypeRef); ++ } ++ } ++ } ++ ++ private void setupFunctionBody(@NotNull Project project, @NotNull JetNamedFunction func) { ++ FileTemplate fileTemplate = FileTemplateManager.getInstance().getCodeTemplate(TEMPLATE_FROM_USAGE_METHOD_BODY); ++ Properties properties = new Properties(); ++ if (isUnit) { ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, ""Unit""); ++ } else { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnTypeRef.getText()); ++ } ++ properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFQName(ownerClassDescriptor).getFqName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, ownerClassDescriptor.getName().getName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_METHOD_NAME, methodName); ++ ++ @NonNls String bodyText; ++ try { ++ bodyText = fileTemplate.getText(properties); ++ } catch (ProcessCanceledException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IncorrectOperationException(""Failed to parse file template"", e); ++ } ++ JetExpression newBodyExpression = JetPsiFactory.createFunctionBody(project, bodyText); ++ JetExpression oldBodyExpression = func.getBodyExpression(); ++ assert oldBodyExpression != null; ++ oldBodyExpression.replace(newBodyExpression); ++ } ++ ++ @NotNull ++ private TypeExpression setupReturnTypeTemplate(@NotNull TemplateBuilder builder, @NotNull JetNamedFunction func) { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ TypeExpression returnTypeExpression = new TypeExpression(returnType); ++ builder.replaceElement(returnTypeRef, returnTypeExpression); ++ return returnTypeExpression; ++ } ++ ++ @NotNull ++ private TypeParameterListExpression setupTypeParameterListTemplate(@NotNull TemplateBuilderImpl builder, @NotNull JetNamedFunction func) { ++ Map typeParameterMap = new HashMap(); ++ String[] receiverTypeParameterNames = selectedReceiverType.getTypeParameterNames(); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ typeParameterMap.put(parameterTypeCandidate.getRenderedType(), parameterTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ typeParameterMap.put(returnTypeCandidate.getRenderedType(), returnTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ builder.replaceElement(func, TextRange.create(3, 3), TYPE_PARAMETER_LIST_VARIABLE_NAME, null, false); // ((3, 3) is after ""fun"") ++ return new TypeParameterListExpression(receiverTypeParameterNames, typeParameterMap); ++ } ++ ++ private TypeExpression[] setupParameterTypeTemplates(@NotNull Project project, @NotNull TemplateBuilder builder, ++ @NotNull JetParameterList parameterList) { ++ List jetParameters = parameterList.getParameters(); ++ assert jetParameters.size() == parameters.size(); ++ TypeExpression[] parameterTypeExpressions = new TypeExpression[parameters.size()]; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(project); ++ for (int i = 0; i < parameters.size(); i++) { ++ Parameter parameter = parameters.get(i); ++ JetParameter jetParameter = jetParameters.get(i); ++ ++ // add parameter type to the template ++ parameterTypeExpressions[i] = new TypeExpression(parameter.getType()); ++ JetTypeReference parameterTypeRef = jetParameter.getTypeReference(); ++ assert parameterTypeRef != null; ++ builder.replaceElement(parameterTypeRef, parameterTypeExpressions[i]); ++ ++ // add parameter name to the template ++ String[] possibleNamesFromExpression = parameter.getType().getPossibleNamesFromExpression(); ++ String preferredName = parameter.getPreferredName(); ++ String[] possibleNames; ++ if (preferredName != null) { ++ possibleNames = new String[possibleNamesFromExpression.length + 1]; ++ possibleNames[0] = preferredName; ++ System.arraycopy(possibleNamesFromExpression, 0, possibleNames, 1, possibleNamesFromExpression.length); ++ } else { ++ possibleNames = possibleNamesFromExpression; ++ } ++ ++ // figure out suggested names for each type option ++ Map parameterTypeToNamesMap = new HashMap(); ++ for (TypeCandidate typeCandidate : parameter.getType().getTypeCandidates()) { ++ String[] suggestedNames = JetNameSuggester.suggestNamesForType(typeCandidate.getType(), dummyValidator); ++ parameterTypeToNamesMap.put(typeCandidate.getRenderedType(), suggestedNames); ++ } ++ ++ // add expression to builder ++ Expression parameterNameExpression = new ParameterNameExpression(possibleNames, parameterTypeToNamesMap); ++ PsiElement parameterNameIdentifier = jetParameter.getNameIdentifier(); ++ assert parameterNameIdentifier != null; ++ builder.replaceElement(parameterNameIdentifier, parameterNameExpression); ++ } ++ return parameterTypeExpressions; ++ } ++ ++ private void replaceWithLongerName(@NotNull Project project, @NotNull JetTypeReference typeRef, @NotNull JetType type) { ++ JetTypeReference fullyQualifiedReceiverTypeRef = JetPsiFactory.createType(project, renderTypeLong(type, typeParameterNameMap)); ++ typeRef.replace(fullyQualifiedReceiverTypeRef); ++ } ++ ++ @NotNull ++ private static JetType substituteType(@NotNull JetType type, @NotNull TypeSubstitution substitution, @NotNull Variance variance) {","I don't understand what does this method do, but I feel that it can be replaced with using already existing `TypeSubstitutor` mechanism. Please check it. +",2013-04-26 11:55:18 +71,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace); ++ } ++ ++ return func; ++ } ++ ++ private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) { ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // build templates ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument()); ++ ++ CaretModel caretModel = containingFileEditor.getCaretModel(); ++ caretModel.moveToOffset(containingFile.getNode().getStartOffset()); ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile); ++ final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); ++ final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); ++ ++ // add a segment for the parameter list ++ // Note: because TemplateBuilderImpl does not have a replaceElement overload that takes in both a TextRange and alwaysStopAt, we ++ // need to create the segment first and then hack the Expression into the template later. We use this template to update the type ++ // parameter list as the user makes selections in the parameter types, and we need alwaysStopAt to be false so the user can't tab to ++ // it. ++ TypeParameterListExpression expression = setupTypeParameterListTemplate(builder, func); ++ ++ // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it ++ final TemplateImpl template = (TemplateImpl) builder.buildInlineTemplate(); ++ ArrayList variables = template.getVariables(); ++ for (int i = 0; i < parameters.size(); i++) { ++ Collections.swap(variables, i * 2, i * 2 + 1); ++ } ++ ++ // fix up the template to include the expression for the type parameter list ++ variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); ++ ++ // run the template ++ TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template _, boolean brokenOff) { ++ // file templates ++ int offset = template.getSegmentOffset(0); ++ final JetNamedFunction func = PsiTreeUtil.findElementOfClassAtOffset(containingFile, offset, JetNamedFunction.class, false); ++ assert func != null; ++ final List typeRefsToShorten = new ArrayList(); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ // file templates ++ setupFunctionBody(project, func); ++ ++ // change short type names to fully qualified ones (to be shortened below) ++ setupTypeReferencesForShortening(project, func, typeRefsToShorten, parameterTypeExpressions, returnTypeExpression); ++ } ++ }); ++ ++ ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten); ++ } ++ }); ++ } ++ ++ private Map getTypeParameterRenames(JetScope scope) { ++ TypeParameterDescriptor[] receiverTypeParametersNotInScope = selectedReceiverType.getTypeParameters(); ++ Set allTypeParametersNotInScope = new LinkedHashSet(); ++ allTypeParametersNotInScope.addAll(Arrays.asList(receiverTypeParametersNotInScope)); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(parameterTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ if (!isUnit) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(returnTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ List typeParameters = new ArrayList(allTypeParametersNotInScope); ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames.add(getNextAvailableName(typeParameter.getName().getName(), typeParameterNames, scope)); ++ } ++ assert typeParameters.size() == typeParameterNames.size(); ++ Map typeParameterNameMap = new HashMap(); ++ for (int i = 0; i < typeParameters.size(); i++) { ++ typeParameterNameMap.put(typeParameters.get(i), typeParameterNames.get(i)); ++ } ++ ++ return typeParameterNameMap; ++ } ++ ++ private void setupTypeReferencesForShortening( ++ @NotNull Project project, ++ @NotNull JetNamedFunction func, ++ @NotNull List typeRefsToShorten, ++ @NotNull TypeExpression[] parameterTypeExpressions, ++ @Nullable TypeExpression returnTypeExpression ++ ) { ++ if (isExtension) { ++ JetTypeReference receiverTypeRef = ++ JetPsiFactory.createType(project, renderTypeLong(selectedReceiverType.getType(), typeParameterNameMap)); ++ replaceWithLongerName(project, receiverTypeRef, selectedReceiverType.getType()); ++ ++ receiverTypeRef = func.getReceiverTypeRef(); ++ if (receiverTypeRef != null) { ++ typeRefsToShorten.add(receiverTypeRef); ++ } ++ } ++ ++ if (!isUnit) { ++ assert returnTypeExpression != null; ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ JetType returnType = returnTypeExpression.getTypeFromSelection(returnTypeRef.getText()); ++ if (returnType != null) { // user selected a given type ++ replaceWithLongerName(project, returnTypeRef, returnType); ++ returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ typeRefsToShorten.add(returnTypeRef); ++ } ++ } ++ } ++ ++ List valueParameters = func.getValueParameters(); ++ List parameterIndicesToShorten = new ArrayList(); ++ assert valueParameters.size() == parameterTypeExpressions.length; ++ for (int i = 0; i < valueParameters.size(); i++) { ++ JetParameter parameter = valueParameters.get(i); ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ JetType parameterType = parameterTypeExpressions[i].getTypeFromSelection(parameterTypeRef.getText()); ++ if (parameterType != null) { ++ replaceWithLongerName(project, parameterTypeRef, parameterType); ++ parameterIndicesToShorten.add(i); ++ } ++ } ++ } ++ valueParameters = func.getValueParameters(); ++ for (int i : parameterIndicesToShorten) { ++ JetTypeReference parameterTypeRef = valueParameters.get(i).getTypeReference(); ++ if (parameterTypeRef != null) { ++ typeRefsToShorten.add(parameterTypeRef); ++ } ++ } ++ } ++ ++ private void setupFunctionBody(@NotNull Project project, @NotNull JetNamedFunction func) { ++ FileTemplate fileTemplate = FileTemplateManager.getInstance().getCodeTemplate(TEMPLATE_FROM_USAGE_METHOD_BODY); ++ Properties properties = new Properties(); ++ if (isUnit) { ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, ""Unit""); ++ } else { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnTypeRef.getText()); ++ } ++ properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFQName(ownerClassDescriptor).getFqName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, ownerClassDescriptor.getName().getName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_METHOD_NAME, methodName); ++ ++ @NonNls String bodyText; ++ try { ++ bodyText = fileTemplate.getText(properties); ++ } catch (ProcessCanceledException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IncorrectOperationException(""Failed to parse file template"", e); ++ } ++ JetExpression newBodyExpression = JetPsiFactory.createFunctionBody(project, bodyText); ++ JetExpression oldBodyExpression = func.getBodyExpression(); ++ assert oldBodyExpression != null; ++ oldBodyExpression.replace(newBodyExpression); ++ } ++ ++ @NotNull ++ private TypeExpression setupReturnTypeTemplate(@NotNull TemplateBuilder builder, @NotNull JetNamedFunction func) { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ TypeExpression returnTypeExpression = new TypeExpression(returnType); ++ builder.replaceElement(returnTypeRef, returnTypeExpression); ++ return returnTypeExpression; ++ } ++ ++ @NotNull ++ private TypeParameterListExpression setupTypeParameterListTemplate(@NotNull TemplateBuilderImpl builder, @NotNull JetNamedFunction func) { ++ Map typeParameterMap = new HashMap(); ++ String[] receiverTypeParameterNames = selectedReceiverType.getTypeParameterNames(); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ typeParameterMap.put(parameterTypeCandidate.getRenderedType(), parameterTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ typeParameterMap.put(returnTypeCandidate.getRenderedType(), returnTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ builder.replaceElement(func, TextRange.create(3, 3), TYPE_PARAMETER_LIST_VARIABLE_NAME, null, false); // ((3, 3) is after ""fun"") ++ return new TypeParameterListExpression(receiverTypeParameterNames, typeParameterMap); ++ } ++ ++ private TypeExpression[] setupParameterTypeTemplates(@NotNull Project project, @NotNull TemplateBuilder builder, ++ @NotNull JetParameterList parameterList) { ++ List jetParameters = parameterList.getParameters(); ++ assert jetParameters.size() == parameters.size(); ++ TypeExpression[] parameterTypeExpressions = new TypeExpression[parameters.size()]; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(project); ++ for (int i = 0; i < parameters.size(); i++) { ++ Parameter parameter = parameters.get(i); ++ JetParameter jetParameter = jetParameters.get(i); ++ ++ // add parameter type to the template ++ parameterTypeExpressions[i] = new TypeExpression(parameter.getType()); ++ JetTypeReference parameterTypeRef = jetParameter.getTypeReference(); ++ assert parameterTypeRef != null; ++ builder.replaceElement(parameterTypeRef, parameterTypeExpressions[i]); ++ ++ // add parameter name to the template ++ String[] possibleNamesFromExpression = parameter.getType().getPossibleNamesFromExpression(); ++ String preferredName = parameter.getPreferredName(); ++ String[] possibleNames; ++ if (preferredName != null) { ++ possibleNames = new String[possibleNamesFromExpression.length + 1]; ++ possibleNames[0] = preferredName; ++ System.arraycopy(possibleNamesFromExpression, 0, possibleNames, 1, possibleNamesFromExpression.length); ++ } else { ++ possibleNames = possibleNamesFromExpression; ++ } ++ ++ // figure out suggested names for each type option ++ Map parameterTypeToNamesMap = new HashMap(); ++ for (TypeCandidate typeCandidate : parameter.getType().getTypeCandidates()) { ++ String[] suggestedNames = JetNameSuggester.suggestNamesForType(typeCandidate.getType(), dummyValidator); ++ parameterTypeToNamesMap.put(typeCandidate.getRenderedType(), suggestedNames); ++ } ++ ++ // add expression to builder ++ Expression parameterNameExpression = new ParameterNameExpression(possibleNames, parameterTypeToNamesMap); ++ PsiElement parameterNameIdentifier = jetParameter.getNameIdentifier(); ++ assert parameterNameIdentifier != null; ++ builder.replaceElement(parameterNameIdentifier, parameterNameExpression); ++ } ++ return parameterTypeExpressions; ++ } ++ ++ private void replaceWithLongerName(@NotNull Project project, @NotNull JetTypeReference typeRef, @NotNull JetType type) { ++ JetTypeReference fullyQualifiedReceiverTypeRef = JetPsiFactory.createType(project, renderTypeLong(type, typeParameterNameMap)); ++ typeRef.replace(fullyQualifiedReceiverTypeRef); ++ } ++ ++ @NotNull ++ private static JetType substituteType(@NotNull JetType type, @NotNull TypeSubstitution substitution, @NotNull Variance variance) { ++ switch (variance) { ++ case INVARIANT: ++ // for invariant, can replace only when they're equal ++ if (type.equals(substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case IN_VARIANCE: ++ // for covariant (e.g. function parameter), can replace type with any of its supertypes","You seem to mix up ""co"" and ""contra"" prefixes. +",2013-04-26 11:55:52 +72,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace); ++ } ++ ++ return func; ++ } ++ ++ private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) { ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // build templates ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument()); ++ ++ CaretModel caretModel = containingFileEditor.getCaretModel(); ++ caretModel.moveToOffset(containingFile.getNode().getStartOffset()); ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile); ++ final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); ++ final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); ++ ++ // add a segment for the parameter list ++ // Note: because TemplateBuilderImpl does not have a replaceElement overload that takes in both a TextRange and alwaysStopAt, we ++ // need to create the segment first and then hack the Expression into the template later. We use this template to update the type ++ // parameter list as the user makes selections in the parameter types, and we need alwaysStopAt to be false so the user can't tab to ++ // it. ++ TypeParameterListExpression expression = setupTypeParameterListTemplate(builder, func); ++ ++ // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it ++ final TemplateImpl template = (TemplateImpl) builder.buildInlineTemplate(); ++ ArrayList variables = template.getVariables(); ++ for (int i = 0; i < parameters.size(); i++) { ++ Collections.swap(variables, i * 2, i * 2 + 1); ++ } ++ ++ // fix up the template to include the expression for the type parameter list ++ variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); ++ ++ // run the template ++ TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template _, boolean brokenOff) { ++ // file templates ++ int offset = template.getSegmentOffset(0); ++ final JetNamedFunction func = PsiTreeUtil.findElementOfClassAtOffset(containingFile, offset, JetNamedFunction.class, false); ++ assert func != null; ++ final List typeRefsToShorten = new ArrayList(); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ // file templates ++ setupFunctionBody(project, func); ++ ++ // change short type names to fully qualified ones (to be shortened below) ++ setupTypeReferencesForShortening(project, func, typeRefsToShorten, parameterTypeExpressions, returnTypeExpression); ++ } ++ }); ++ ++ ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten); ++ } ++ }); ++ } ++ ++ private Map getTypeParameterRenames(JetScope scope) { ++ TypeParameterDescriptor[] receiverTypeParametersNotInScope = selectedReceiverType.getTypeParameters(); ++ Set allTypeParametersNotInScope = new LinkedHashSet(); ++ allTypeParametersNotInScope.addAll(Arrays.asList(receiverTypeParametersNotInScope)); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(parameterTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ if (!isUnit) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(returnTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ List typeParameters = new ArrayList(allTypeParametersNotInScope); ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames.add(getNextAvailableName(typeParameter.getName().getName(), typeParameterNames, scope)); ++ } ++ assert typeParameters.size() == typeParameterNames.size(); ++ Map typeParameterNameMap = new HashMap(); ++ for (int i = 0; i < typeParameters.size(); i++) { ++ typeParameterNameMap.put(typeParameters.get(i), typeParameterNames.get(i)); ++ } ++ ++ return typeParameterNameMap; ++ } ++ ++ private void setupTypeReferencesForShortening( ++ @NotNull Project project, ++ @NotNull JetNamedFunction func, ++ @NotNull List typeRefsToShorten, ++ @NotNull TypeExpression[] parameterTypeExpressions, ++ @Nullable TypeExpression returnTypeExpression ++ ) { ++ if (isExtension) { ++ JetTypeReference receiverTypeRef = ++ JetPsiFactory.createType(project, renderTypeLong(selectedReceiverType.getType(), typeParameterNameMap)); ++ replaceWithLongerName(project, receiverTypeRef, selectedReceiverType.getType()); ++ ++ receiverTypeRef = func.getReceiverTypeRef(); ++ if (receiverTypeRef != null) { ++ typeRefsToShorten.add(receiverTypeRef); ++ } ++ } ++ ++ if (!isUnit) { ++ assert returnTypeExpression != null; ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ JetType returnType = returnTypeExpression.getTypeFromSelection(returnTypeRef.getText()); ++ if (returnType != null) { // user selected a given type ++ replaceWithLongerName(project, returnTypeRef, returnType); ++ returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ typeRefsToShorten.add(returnTypeRef); ++ } ++ } ++ } ++ ++ List valueParameters = func.getValueParameters(); ++ List parameterIndicesToShorten = new ArrayList(); ++ assert valueParameters.size() == parameterTypeExpressions.length; ++ for (int i = 0; i < valueParameters.size(); i++) { ++ JetParameter parameter = valueParameters.get(i); ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ JetType parameterType = parameterTypeExpressions[i].getTypeFromSelection(parameterTypeRef.getText()); ++ if (parameterType != null) { ++ replaceWithLongerName(project, parameterTypeRef, parameterType); ++ parameterIndicesToShorten.add(i); ++ } ++ } ++ } ++ valueParameters = func.getValueParameters(); ++ for (int i : parameterIndicesToShorten) { ++ JetTypeReference parameterTypeRef = valueParameters.get(i).getTypeReference(); ++ if (parameterTypeRef != null) { ++ typeRefsToShorten.add(parameterTypeRef); ++ } ++ } ++ } ++ ++ private void setupFunctionBody(@NotNull Project project, @NotNull JetNamedFunction func) { ++ FileTemplate fileTemplate = FileTemplateManager.getInstance().getCodeTemplate(TEMPLATE_FROM_USAGE_METHOD_BODY); ++ Properties properties = new Properties(); ++ if (isUnit) { ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, ""Unit""); ++ } else { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnTypeRef.getText()); ++ } ++ properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFQName(ownerClassDescriptor).getFqName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, ownerClassDescriptor.getName().getName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_METHOD_NAME, methodName); ++ ++ @NonNls String bodyText; ++ try { ++ bodyText = fileTemplate.getText(properties); ++ } catch (ProcessCanceledException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IncorrectOperationException(""Failed to parse file template"", e); ++ } ++ JetExpression newBodyExpression = JetPsiFactory.createFunctionBody(project, bodyText); ++ JetExpression oldBodyExpression = func.getBodyExpression(); ++ assert oldBodyExpression != null; ++ oldBodyExpression.replace(newBodyExpression); ++ } ++ ++ @NotNull ++ private TypeExpression setupReturnTypeTemplate(@NotNull TemplateBuilder builder, @NotNull JetNamedFunction func) { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ TypeExpression returnTypeExpression = new TypeExpression(returnType); ++ builder.replaceElement(returnTypeRef, returnTypeExpression); ++ return returnTypeExpression; ++ } ++ ++ @NotNull ++ private TypeParameterListExpression setupTypeParameterListTemplate(@NotNull TemplateBuilderImpl builder, @NotNull JetNamedFunction func) { ++ Map typeParameterMap = new HashMap(); ++ String[] receiverTypeParameterNames = selectedReceiverType.getTypeParameterNames(); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ typeParameterMap.put(parameterTypeCandidate.getRenderedType(), parameterTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ typeParameterMap.put(returnTypeCandidate.getRenderedType(), returnTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ builder.replaceElement(func, TextRange.create(3, 3), TYPE_PARAMETER_LIST_VARIABLE_NAME, null, false); // ((3, 3) is after ""fun"") ++ return new TypeParameterListExpression(receiverTypeParameterNames, typeParameterMap); ++ } ++ ++ private TypeExpression[] setupParameterTypeTemplates(@NotNull Project project, @NotNull TemplateBuilder builder, ++ @NotNull JetParameterList parameterList) { ++ List jetParameters = parameterList.getParameters(); ++ assert jetParameters.size() == parameters.size(); ++ TypeExpression[] parameterTypeExpressions = new TypeExpression[parameters.size()]; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(project); ++ for (int i = 0; i < parameters.size(); i++) { ++ Parameter parameter = parameters.get(i); ++ JetParameter jetParameter = jetParameters.get(i); ++ ++ // add parameter type to the template ++ parameterTypeExpressions[i] = new TypeExpression(parameter.getType()); ++ JetTypeReference parameterTypeRef = jetParameter.getTypeReference(); ++ assert parameterTypeRef != null; ++ builder.replaceElement(parameterTypeRef, parameterTypeExpressions[i]); ++ ++ // add parameter name to the template ++ String[] possibleNamesFromExpression = parameter.getType().getPossibleNamesFromExpression(); ++ String preferredName = parameter.getPreferredName(); ++ String[] possibleNames; ++ if (preferredName != null) { ++ possibleNames = new String[possibleNamesFromExpression.length + 1]; ++ possibleNames[0] = preferredName; ++ System.arraycopy(possibleNamesFromExpression, 0, possibleNames, 1, possibleNamesFromExpression.length); ++ } else { ++ possibleNames = possibleNamesFromExpression; ++ } ++ ++ // figure out suggested names for each type option ++ Map parameterTypeToNamesMap = new HashMap(); ++ for (TypeCandidate typeCandidate : parameter.getType().getTypeCandidates()) { ++ String[] suggestedNames = JetNameSuggester.suggestNamesForType(typeCandidate.getType(), dummyValidator); ++ parameterTypeToNamesMap.put(typeCandidate.getRenderedType(), suggestedNames); ++ } ++ ++ // add expression to builder ++ Expression parameterNameExpression = new ParameterNameExpression(possibleNames, parameterTypeToNamesMap); ++ PsiElement parameterNameIdentifier = jetParameter.getNameIdentifier(); ++ assert parameterNameIdentifier != null; ++ builder.replaceElement(parameterNameIdentifier, parameterNameExpression); ++ } ++ return parameterTypeExpressions; ++ } ++ ++ private void replaceWithLongerName(@NotNull Project project, @NotNull JetTypeReference typeRef, @NotNull JetType type) { ++ JetTypeReference fullyQualifiedReceiverTypeRef = JetPsiFactory.createType(project, renderTypeLong(type, typeParameterNameMap)); ++ typeRef.replace(fullyQualifiedReceiverTypeRef); ++ } ++ ++ @NotNull ++ private static JetType substituteType(@NotNull JetType type, @NotNull TypeSubstitution substitution, @NotNull Variance variance) { ++ switch (variance) { ++ case INVARIANT: ++ // for invariant, can replace only when they're equal ++ if (type.equals(substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case IN_VARIANCE: ++ // for covariant (e.g. function parameter), can replace type with any of its supertypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(type, substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case OUT_VARIANCE: ++ // for contravariant (e.g. function return value), can replace type with any of its subtypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(substitution.getForType(), type)) { ++ return substitution.getByType(); ++ } ++ break; ++ } ++ ++ List newArguments = new ArrayList(); ++ List typeParameters = type.getConstructor().getParameters(); ++ int i = 0; ++ for (TypeProjection projection : type.getArguments()) { ++ TypeParameterDescriptor typeParameter = typeParameters.get(i); ++ JetType newArgument = substituteType(projection.getType(), substitution, typeParameter.getVariance()); ++ newArguments.add(new TypeProjection(Variance.INVARIANT, newArgument)); ++ i++; ++ } ++ return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), ++ type.isNullable(), newArguments, type.getMemberScope()); ++ } ++ ++ private static boolean containsType(JetType outer, JetType inner) { ++ if (outer.equals(inner)) { ++ return true; ++ } ++ ++ for (TypeProjection projection : outer.getArguments()) { ++ if (containsType(projection.getType(), inner)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @NotNull ++ private static String renderDescriptor( ++ @NotNull DeclarationDescriptor declarationDescriptor, ++ @NotNull Map typeParameterNameMap, ++ boolean fq ++ ) { ++ if (declarationDescriptor instanceof TypeParameterDescriptor) { ++ String replacement = typeParameterNameMap.get(declarationDescriptor); ++ return replacement == null ? declarationDescriptor.getName().getName() : replacement; ++ } else { ++ return fq ? DescriptorUtils.getFQName(declarationDescriptor).getFqName() : declarationDescriptor.getName().getName(); ++ } ++ } ++ ++ @NotNull ++ private static String renderDescriptor(@NotNull DeclarationDescriptor declarationDescriptor, boolean fq) { ++ return renderDescriptor(declarationDescriptor, Collections.emptyMap(), fq); ++ } ++ ++ private static String renderType(@NotNull JetType type, @NotNull Map typeParameterNameMap, boolean fq) { ++ List projections = type.getArguments(); ++ DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); ++ assert declarationDescriptor != null; ++ if (projections.isEmpty()) { ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq); ++ } ++ ++ List arguments = new ArrayList(); ++ for (TypeProjection projection : projections) { ++ arguments.add(renderType(projection.getType(), typeParameterNameMap, fq)); ++ } ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq) + ""<"" + StringUtil.join(arguments, "", "") + "">""; ++ } ++ ++ @NotNull ++ private static String renderTypeShort(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, false); ++ } ++ ++ @NotNull ++ private static String renderTypeLong(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, true); ++ } ++ ++ @NotNull ++ private static TypeParameterDescriptor[] getTypeParameterNamesNotInScope( ++ @NotNull Collection typeParameters, ++ @NotNull JetScope scope ++ ) { ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ ClassifierDescriptor classifier = scope.getClassifier(typeParameter.getName()); ++ if (classifier == null || !classifier.equals(typeParameter)) { ++ typeParameterNames.add(typeParameter); ++ } ++ } ++ return typeParameterNames.toArray(new TypeParameterDescriptor[typeParameterNames.size()]); ++ } ++ ++ @NotNull ++ private static Set getTypeParametersInType(@NotNull JetType type) { ++ Set typeParameters = new LinkedHashSet(); ++ List arguments = type.getArguments(); ++ if (arguments.isEmpty()) { ++ ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); ++ if (descriptor instanceof TypeParameterDescriptor) { ++ typeParameters.add((TypeParameterDescriptor) descriptor); ++ } ++ } else { ++ for (TypeProjection projection : arguments) { ++ typeParameters.addAll(getTypeParametersInType(projection.getType())); ++ } ++ } ++ return typeParameters; ++ } ++ ++ @NotNull ++ private static String getNextAvailableName(@NotNull String name, @NotNull Collection existingNames) {","I think, it's better to merge this and next method (with `@Nullable` scope) +Add comment, that for Foo name from parameter it returns itself, if it is available, and Foo1, Foo2, .. if it's not. +",2013-04-26 11:56:49 +73,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace); ++ } ++ ++ return func; ++ } ++ ++ private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) { ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // build templates ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument()); ++ ++ CaretModel caretModel = containingFileEditor.getCaretModel(); ++ caretModel.moveToOffset(containingFile.getNode().getStartOffset()); ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile); ++ final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); ++ final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); ++ ++ // add a segment for the parameter list ++ // Note: because TemplateBuilderImpl does not have a replaceElement overload that takes in both a TextRange and alwaysStopAt, we ++ // need to create the segment first and then hack the Expression into the template later. We use this template to update the type ++ // parameter list as the user makes selections in the parameter types, and we need alwaysStopAt to be false so the user can't tab to ++ // it. ++ TypeParameterListExpression expression = setupTypeParameterListTemplate(builder, func); ++ ++ // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it ++ final TemplateImpl template = (TemplateImpl) builder.buildInlineTemplate(); ++ ArrayList variables = template.getVariables(); ++ for (int i = 0; i < parameters.size(); i++) { ++ Collections.swap(variables, i * 2, i * 2 + 1); ++ } ++ ++ // fix up the template to include the expression for the type parameter list ++ variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); ++ ++ // run the template ++ TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template _, boolean brokenOff) { ++ // file templates ++ int offset = template.getSegmentOffset(0); ++ final JetNamedFunction func = PsiTreeUtil.findElementOfClassAtOffset(containingFile, offset, JetNamedFunction.class, false); ++ assert func != null; ++ final List typeRefsToShorten = new ArrayList(); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ // file templates ++ setupFunctionBody(project, func); ++ ++ // change short type names to fully qualified ones (to be shortened below) ++ setupTypeReferencesForShortening(project, func, typeRefsToShorten, parameterTypeExpressions, returnTypeExpression); ++ } ++ }); ++ ++ ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten); ++ } ++ }); ++ } ++ ++ private Map getTypeParameterRenames(JetScope scope) { ++ TypeParameterDescriptor[] receiverTypeParametersNotInScope = selectedReceiverType.getTypeParameters(); ++ Set allTypeParametersNotInScope = new LinkedHashSet(); ++ allTypeParametersNotInScope.addAll(Arrays.asList(receiverTypeParametersNotInScope)); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(parameterTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ if (!isUnit) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(returnTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ List typeParameters = new ArrayList(allTypeParametersNotInScope); ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames.add(getNextAvailableName(typeParameter.getName().getName(), typeParameterNames, scope)); ++ } ++ assert typeParameters.size() == typeParameterNames.size(); ++ Map typeParameterNameMap = new HashMap(); ++ for (int i = 0; i < typeParameters.size(); i++) { ++ typeParameterNameMap.put(typeParameters.get(i), typeParameterNames.get(i)); ++ } ++ ++ return typeParameterNameMap; ++ } ++ ++ private void setupTypeReferencesForShortening( ++ @NotNull Project project, ++ @NotNull JetNamedFunction func, ++ @NotNull List typeRefsToShorten, ++ @NotNull TypeExpression[] parameterTypeExpressions, ++ @Nullable TypeExpression returnTypeExpression ++ ) { ++ if (isExtension) { ++ JetTypeReference receiverTypeRef = ++ JetPsiFactory.createType(project, renderTypeLong(selectedReceiverType.getType(), typeParameterNameMap)); ++ replaceWithLongerName(project, receiverTypeRef, selectedReceiverType.getType()); ++ ++ receiverTypeRef = func.getReceiverTypeRef(); ++ if (receiverTypeRef != null) { ++ typeRefsToShorten.add(receiverTypeRef); ++ } ++ } ++ ++ if (!isUnit) { ++ assert returnTypeExpression != null; ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ JetType returnType = returnTypeExpression.getTypeFromSelection(returnTypeRef.getText()); ++ if (returnType != null) { // user selected a given type ++ replaceWithLongerName(project, returnTypeRef, returnType); ++ returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ typeRefsToShorten.add(returnTypeRef); ++ } ++ } ++ } ++ ++ List valueParameters = func.getValueParameters(); ++ List parameterIndicesToShorten = new ArrayList(); ++ assert valueParameters.size() == parameterTypeExpressions.length; ++ for (int i = 0; i < valueParameters.size(); i++) { ++ JetParameter parameter = valueParameters.get(i); ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ JetType parameterType = parameterTypeExpressions[i].getTypeFromSelection(parameterTypeRef.getText()); ++ if (parameterType != null) { ++ replaceWithLongerName(project, parameterTypeRef, parameterType); ++ parameterIndicesToShorten.add(i); ++ } ++ } ++ } ++ valueParameters = func.getValueParameters(); ++ for (int i : parameterIndicesToShorten) { ++ JetTypeReference parameterTypeRef = valueParameters.get(i).getTypeReference(); ++ if (parameterTypeRef != null) { ++ typeRefsToShorten.add(parameterTypeRef); ++ } ++ } ++ } ++ ++ private void setupFunctionBody(@NotNull Project project, @NotNull JetNamedFunction func) { ++ FileTemplate fileTemplate = FileTemplateManager.getInstance().getCodeTemplate(TEMPLATE_FROM_USAGE_METHOD_BODY); ++ Properties properties = new Properties(); ++ if (isUnit) { ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, ""Unit""); ++ } else { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnTypeRef.getText()); ++ } ++ properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFQName(ownerClassDescriptor).getFqName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, ownerClassDescriptor.getName().getName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_METHOD_NAME, methodName); ++ ++ @NonNls String bodyText; ++ try { ++ bodyText = fileTemplate.getText(properties); ++ } catch (ProcessCanceledException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IncorrectOperationException(""Failed to parse file template"", e); ++ } ++ JetExpression newBodyExpression = JetPsiFactory.createFunctionBody(project, bodyText); ++ JetExpression oldBodyExpression = func.getBodyExpression(); ++ assert oldBodyExpression != null; ++ oldBodyExpression.replace(newBodyExpression); ++ } ++ ++ @NotNull ++ private TypeExpression setupReturnTypeTemplate(@NotNull TemplateBuilder builder, @NotNull JetNamedFunction func) { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ TypeExpression returnTypeExpression = new TypeExpression(returnType); ++ builder.replaceElement(returnTypeRef, returnTypeExpression); ++ return returnTypeExpression; ++ } ++ ++ @NotNull ++ private TypeParameterListExpression setupTypeParameterListTemplate(@NotNull TemplateBuilderImpl builder, @NotNull JetNamedFunction func) { ++ Map typeParameterMap = new HashMap(); ++ String[] receiverTypeParameterNames = selectedReceiverType.getTypeParameterNames(); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ typeParameterMap.put(parameterTypeCandidate.getRenderedType(), parameterTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ typeParameterMap.put(returnTypeCandidate.getRenderedType(), returnTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ builder.replaceElement(func, TextRange.create(3, 3), TYPE_PARAMETER_LIST_VARIABLE_NAME, null, false); // ((3, 3) is after ""fun"") ++ return new TypeParameterListExpression(receiverTypeParameterNames, typeParameterMap); ++ } ++ ++ private TypeExpression[] setupParameterTypeTemplates(@NotNull Project project, @NotNull TemplateBuilder builder, ++ @NotNull JetParameterList parameterList) { ++ List jetParameters = parameterList.getParameters(); ++ assert jetParameters.size() == parameters.size(); ++ TypeExpression[] parameterTypeExpressions = new TypeExpression[parameters.size()]; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(project); ++ for (int i = 0; i < parameters.size(); i++) { ++ Parameter parameter = parameters.get(i); ++ JetParameter jetParameter = jetParameters.get(i); ++ ++ // add parameter type to the template ++ parameterTypeExpressions[i] = new TypeExpression(parameter.getType()); ++ JetTypeReference parameterTypeRef = jetParameter.getTypeReference(); ++ assert parameterTypeRef != null; ++ builder.replaceElement(parameterTypeRef, parameterTypeExpressions[i]); ++ ++ // add parameter name to the template ++ String[] possibleNamesFromExpression = parameter.getType().getPossibleNamesFromExpression(); ++ String preferredName = parameter.getPreferredName(); ++ String[] possibleNames; ++ if (preferredName != null) { ++ possibleNames = new String[possibleNamesFromExpression.length + 1]; ++ possibleNames[0] = preferredName; ++ System.arraycopy(possibleNamesFromExpression, 0, possibleNames, 1, possibleNamesFromExpression.length); ++ } else { ++ possibleNames = possibleNamesFromExpression; ++ } ++ ++ // figure out suggested names for each type option ++ Map parameterTypeToNamesMap = new HashMap(); ++ for (TypeCandidate typeCandidate : parameter.getType().getTypeCandidates()) { ++ String[] suggestedNames = JetNameSuggester.suggestNamesForType(typeCandidate.getType(), dummyValidator); ++ parameterTypeToNamesMap.put(typeCandidate.getRenderedType(), suggestedNames); ++ } ++ ++ // add expression to builder ++ Expression parameterNameExpression = new ParameterNameExpression(possibleNames, parameterTypeToNamesMap); ++ PsiElement parameterNameIdentifier = jetParameter.getNameIdentifier(); ++ assert parameterNameIdentifier != null; ++ builder.replaceElement(parameterNameIdentifier, parameterNameExpression); ++ } ++ return parameterTypeExpressions; ++ } ++ ++ private void replaceWithLongerName(@NotNull Project project, @NotNull JetTypeReference typeRef, @NotNull JetType type) { ++ JetTypeReference fullyQualifiedReceiverTypeRef = JetPsiFactory.createType(project, renderTypeLong(type, typeParameterNameMap)); ++ typeRef.replace(fullyQualifiedReceiverTypeRef); ++ } ++ ++ @NotNull ++ private static JetType substituteType(@NotNull JetType type, @NotNull TypeSubstitution substitution, @NotNull Variance variance) { ++ switch (variance) { ++ case INVARIANT: ++ // for invariant, can replace only when they're equal ++ if (type.equals(substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case IN_VARIANCE: ++ // for covariant (e.g. function parameter), can replace type with any of its supertypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(type, substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case OUT_VARIANCE: ++ // for contravariant (e.g. function return value), can replace type with any of its subtypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(substitution.getForType(), type)) { ++ return substitution.getByType(); ++ } ++ break; ++ } ++ ++ List newArguments = new ArrayList(); ++ List typeParameters = type.getConstructor().getParameters(); ++ int i = 0; ++ for (TypeProjection projection : type.getArguments()) { ++ TypeParameterDescriptor typeParameter = typeParameters.get(i); ++ JetType newArgument = substituteType(projection.getType(), substitution, typeParameter.getVariance()); ++ newArguments.add(new TypeProjection(Variance.INVARIANT, newArgument)); ++ i++; ++ } ++ return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), ++ type.isNullable(), newArguments, type.getMemberScope()); ++ } ++ ++ private static boolean containsType(JetType outer, JetType inner) { ++ if (outer.equals(inner)) { ++ return true; ++ } ++ ++ for (TypeProjection projection : outer.getArguments()) { ++ if (containsType(projection.getType(), inner)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @NotNull ++ private static String renderDescriptor( ++ @NotNull DeclarationDescriptor declarationDescriptor, ++ @NotNull Map typeParameterNameMap, ++ boolean fq ++ ) { ++ if (declarationDescriptor instanceof TypeParameterDescriptor) { ++ String replacement = typeParameterNameMap.get(declarationDescriptor); ++ return replacement == null ? declarationDescriptor.getName().getName() : replacement; ++ } else { ++ return fq ? DescriptorUtils.getFQName(declarationDescriptor).getFqName() : declarationDescriptor.getName().getName(); ++ } ++ } ++ ++ @NotNull ++ private static String renderDescriptor(@NotNull DeclarationDescriptor declarationDescriptor, boolean fq) { ++ return renderDescriptor(declarationDescriptor, Collections.emptyMap(), fq); ++ } ++ ++ private static String renderType(@NotNull JetType type, @NotNull Map typeParameterNameMap, boolean fq) { ++ List projections = type.getArguments(); ++ DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); ++ assert declarationDescriptor != null; ++ if (projections.isEmpty()) { ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq); ++ } ++ ++ List arguments = new ArrayList(); ++ for (TypeProjection projection : projections) { ++ arguments.add(renderType(projection.getType(), typeParameterNameMap, fq)); ++ } ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq) + ""<"" + StringUtil.join(arguments, "", "") + "">""; ++ } ++ ++ @NotNull ++ private static String renderTypeShort(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, false); ++ } ++ ++ @NotNull ++ private static String renderTypeLong(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, true); ++ } ++ ++ @NotNull ++ private static TypeParameterDescriptor[] getTypeParameterNamesNotInScope( ++ @NotNull Collection typeParameters, ++ @NotNull JetScope scope ++ ) { ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ ClassifierDescriptor classifier = scope.getClassifier(typeParameter.getName()); ++ if (classifier == null || !classifier.equals(typeParameter)) { ++ typeParameterNames.add(typeParameter); ++ } ++ } ++ return typeParameterNames.toArray(new TypeParameterDescriptor[typeParameterNames.size()]); ++ } ++ ++ @NotNull ++ private static Set getTypeParametersInType(@NotNull JetType type) { ++ Set typeParameters = new LinkedHashSet(); ++ List arguments = type.getArguments(); ++ if (arguments.isEmpty()) { ++ ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); ++ if (descriptor instanceof TypeParameterDescriptor) { ++ typeParameters.add((TypeParameterDescriptor) descriptor); ++ } ++ } else { ++ for (TypeProjection projection : arguments) { ++ typeParameters.addAll(getTypeParametersInType(projection.getType())); ++ } ++ } ++ return typeParameters; ++ } ++ ++ @NotNull ++ private static String getNextAvailableName(@NotNull String name, @NotNull Collection existingNames) { ++ if (existingNames.contains(name)) { ++ int j = 1; ++ while (existingNames.contains(name + j)) j++; ++ name += j; ++ } ++ return name; ++ } ++ ++ @NotNull ++ private static String getNextAvailableName(@NotNull String name, @NotNull Collection existingNames, @NotNull JetScope scope) { ++ if (existingNames.contains(name) || scope.getClassifier(Name.identifier(name)) != null) { ++ int j = 1; ++ while (existingNames.contains(name + j) || scope.getClassifier(Name.identifier(name + j)) != null) j++; ++ name += j; ++ } ++ return name; ++ } ++ ++ @NotNull ++ private static JetType[] guessTypeForExpression(@NotNull JetExpression expr, @NotNull BindingContext context) {","If this method returns several types, maybe it should be named `guessTypes...`? + +The method is very complex. +- Reassigning local variables is usually a bad style, because it makes code harder to comprehend and refactor. +- Combination of reassignments and deep if-else-if is even worse. + I offer extracting method guessTypesForDeclaration and use it immediately instead of assigning to declaration. This will allow removing reassigned variable and make each `if` end with `return`, and `else`s will be unnecessary. +",2013-04-26 11:58:12 +74,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace); ++ } ++ ++ return func; ++ } ++ ++ private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) { ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // build templates ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument()); ++ ++ CaretModel caretModel = containingFileEditor.getCaretModel(); ++ caretModel.moveToOffset(containingFile.getNode().getStartOffset()); ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile); ++ final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); ++ final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); ++ ++ // add a segment for the parameter list ++ // Note: because TemplateBuilderImpl does not have a replaceElement overload that takes in both a TextRange and alwaysStopAt, we ++ // need to create the segment first and then hack the Expression into the template later. We use this template to update the type ++ // parameter list as the user makes selections in the parameter types, and we need alwaysStopAt to be false so the user can't tab to ++ // it. ++ TypeParameterListExpression expression = setupTypeParameterListTemplate(builder, func); ++ ++ // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it ++ final TemplateImpl template = (TemplateImpl) builder.buildInlineTemplate(); ++ ArrayList variables = template.getVariables(); ++ for (int i = 0; i < parameters.size(); i++) { ++ Collections.swap(variables, i * 2, i * 2 + 1); ++ } ++ ++ // fix up the template to include the expression for the type parameter list ++ variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); ++ ++ // run the template ++ TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template _, boolean brokenOff) { ++ // file templates ++ int offset = template.getSegmentOffset(0); ++ final JetNamedFunction func = PsiTreeUtil.findElementOfClassAtOffset(containingFile, offset, JetNamedFunction.class, false); ++ assert func != null; ++ final List typeRefsToShorten = new ArrayList(); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ // file templates ++ setupFunctionBody(project, func); ++ ++ // change short type names to fully qualified ones (to be shortened below) ++ setupTypeReferencesForShortening(project, func, typeRefsToShorten, parameterTypeExpressions, returnTypeExpression); ++ } ++ }); ++ ++ ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten); ++ } ++ }); ++ } ++ ++ private Map getTypeParameterRenames(JetScope scope) { ++ TypeParameterDescriptor[] receiverTypeParametersNotInScope = selectedReceiverType.getTypeParameters(); ++ Set allTypeParametersNotInScope = new LinkedHashSet(); ++ allTypeParametersNotInScope.addAll(Arrays.asList(receiverTypeParametersNotInScope)); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(parameterTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ if (!isUnit) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(returnTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ List typeParameters = new ArrayList(allTypeParametersNotInScope); ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames.add(getNextAvailableName(typeParameter.getName().getName(), typeParameterNames, scope)); ++ } ++ assert typeParameters.size() == typeParameterNames.size(); ++ Map typeParameterNameMap = new HashMap(); ++ for (int i = 0; i < typeParameters.size(); i++) { ++ typeParameterNameMap.put(typeParameters.get(i), typeParameterNames.get(i)); ++ } ++ ++ return typeParameterNameMap; ++ } ++ ++ private void setupTypeReferencesForShortening( ++ @NotNull Project project, ++ @NotNull JetNamedFunction func, ++ @NotNull List typeRefsToShorten, ++ @NotNull TypeExpression[] parameterTypeExpressions, ++ @Nullable TypeExpression returnTypeExpression ++ ) { ++ if (isExtension) { ++ JetTypeReference receiverTypeRef = ++ JetPsiFactory.createType(project, renderTypeLong(selectedReceiverType.getType(), typeParameterNameMap)); ++ replaceWithLongerName(project, receiverTypeRef, selectedReceiverType.getType()); ++ ++ receiverTypeRef = func.getReceiverTypeRef(); ++ if (receiverTypeRef != null) { ++ typeRefsToShorten.add(receiverTypeRef); ++ } ++ } ++ ++ if (!isUnit) { ++ assert returnTypeExpression != null; ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ JetType returnType = returnTypeExpression.getTypeFromSelection(returnTypeRef.getText()); ++ if (returnType != null) { // user selected a given type ++ replaceWithLongerName(project, returnTypeRef, returnType); ++ returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ typeRefsToShorten.add(returnTypeRef); ++ } ++ } ++ } ++ ++ List valueParameters = func.getValueParameters(); ++ List parameterIndicesToShorten = new ArrayList(); ++ assert valueParameters.size() == parameterTypeExpressions.length; ++ for (int i = 0; i < valueParameters.size(); i++) { ++ JetParameter parameter = valueParameters.get(i); ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ JetType parameterType = parameterTypeExpressions[i].getTypeFromSelection(parameterTypeRef.getText()); ++ if (parameterType != null) { ++ replaceWithLongerName(project, parameterTypeRef, parameterType); ++ parameterIndicesToShorten.add(i); ++ } ++ } ++ } ++ valueParameters = func.getValueParameters(); ++ for (int i : parameterIndicesToShorten) { ++ JetTypeReference parameterTypeRef = valueParameters.get(i).getTypeReference(); ++ if (parameterTypeRef != null) { ++ typeRefsToShorten.add(parameterTypeRef); ++ } ++ } ++ } ++ ++ private void setupFunctionBody(@NotNull Project project, @NotNull JetNamedFunction func) { ++ FileTemplate fileTemplate = FileTemplateManager.getInstance().getCodeTemplate(TEMPLATE_FROM_USAGE_METHOD_BODY); ++ Properties properties = new Properties(); ++ if (isUnit) { ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, ""Unit""); ++ } else { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnTypeRef.getText()); ++ } ++ properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFQName(ownerClassDescriptor).getFqName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, ownerClassDescriptor.getName().getName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_METHOD_NAME, methodName); ++ ++ @NonNls String bodyText; ++ try { ++ bodyText = fileTemplate.getText(properties); ++ } catch (ProcessCanceledException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IncorrectOperationException(""Failed to parse file template"", e); ++ } ++ JetExpression newBodyExpression = JetPsiFactory.createFunctionBody(project, bodyText); ++ JetExpression oldBodyExpression = func.getBodyExpression(); ++ assert oldBodyExpression != null; ++ oldBodyExpression.replace(newBodyExpression); ++ } ++ ++ @NotNull ++ private TypeExpression setupReturnTypeTemplate(@NotNull TemplateBuilder builder, @NotNull JetNamedFunction func) { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ TypeExpression returnTypeExpression = new TypeExpression(returnType); ++ builder.replaceElement(returnTypeRef, returnTypeExpression); ++ return returnTypeExpression; ++ } ++ ++ @NotNull ++ private TypeParameterListExpression setupTypeParameterListTemplate(@NotNull TemplateBuilderImpl builder, @NotNull JetNamedFunction func) { ++ Map typeParameterMap = new HashMap(); ++ String[] receiverTypeParameterNames = selectedReceiverType.getTypeParameterNames(); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ typeParameterMap.put(parameterTypeCandidate.getRenderedType(), parameterTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ typeParameterMap.put(returnTypeCandidate.getRenderedType(), returnTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ builder.replaceElement(func, TextRange.create(3, 3), TYPE_PARAMETER_LIST_VARIABLE_NAME, null, false); // ((3, 3) is after ""fun"") ++ return new TypeParameterListExpression(receiverTypeParameterNames, typeParameterMap); ++ } ++ ++ private TypeExpression[] setupParameterTypeTemplates(@NotNull Project project, @NotNull TemplateBuilder builder, ++ @NotNull JetParameterList parameterList) { ++ List jetParameters = parameterList.getParameters(); ++ assert jetParameters.size() == parameters.size(); ++ TypeExpression[] parameterTypeExpressions = new TypeExpression[parameters.size()]; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(project); ++ for (int i = 0; i < parameters.size(); i++) { ++ Parameter parameter = parameters.get(i); ++ JetParameter jetParameter = jetParameters.get(i); ++ ++ // add parameter type to the template ++ parameterTypeExpressions[i] = new TypeExpression(parameter.getType()); ++ JetTypeReference parameterTypeRef = jetParameter.getTypeReference(); ++ assert parameterTypeRef != null; ++ builder.replaceElement(parameterTypeRef, parameterTypeExpressions[i]); ++ ++ // add parameter name to the template ++ String[] possibleNamesFromExpression = parameter.getType().getPossibleNamesFromExpression(); ++ String preferredName = parameter.getPreferredName(); ++ String[] possibleNames; ++ if (preferredName != null) { ++ possibleNames = new String[possibleNamesFromExpression.length + 1]; ++ possibleNames[0] = preferredName; ++ System.arraycopy(possibleNamesFromExpression, 0, possibleNames, 1, possibleNamesFromExpression.length); ++ } else { ++ possibleNames = possibleNamesFromExpression; ++ } ++ ++ // figure out suggested names for each type option ++ Map parameterTypeToNamesMap = new HashMap(); ++ for (TypeCandidate typeCandidate : parameter.getType().getTypeCandidates()) { ++ String[] suggestedNames = JetNameSuggester.suggestNamesForType(typeCandidate.getType(), dummyValidator); ++ parameterTypeToNamesMap.put(typeCandidate.getRenderedType(), suggestedNames); ++ } ++ ++ // add expression to builder ++ Expression parameterNameExpression = new ParameterNameExpression(possibleNames, parameterTypeToNamesMap); ++ PsiElement parameterNameIdentifier = jetParameter.getNameIdentifier(); ++ assert parameterNameIdentifier != null; ++ builder.replaceElement(parameterNameIdentifier, parameterNameExpression); ++ } ++ return parameterTypeExpressions; ++ } ++ ++ private void replaceWithLongerName(@NotNull Project project, @NotNull JetTypeReference typeRef, @NotNull JetType type) { ++ JetTypeReference fullyQualifiedReceiverTypeRef = JetPsiFactory.createType(project, renderTypeLong(type, typeParameterNameMap)); ++ typeRef.replace(fullyQualifiedReceiverTypeRef); ++ } ++ ++ @NotNull ++ private static JetType substituteType(@NotNull JetType type, @NotNull TypeSubstitution substitution, @NotNull Variance variance) { ++ switch (variance) { ++ case INVARIANT: ++ // for invariant, can replace only when they're equal ++ if (type.equals(substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case IN_VARIANCE: ++ // for covariant (e.g. function parameter), can replace type with any of its supertypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(type, substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case OUT_VARIANCE: ++ // for contravariant (e.g. function return value), can replace type with any of its subtypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(substitution.getForType(), type)) { ++ return substitution.getByType(); ++ } ++ break; ++ } ++ ++ List newArguments = new ArrayList(); ++ List typeParameters = type.getConstructor().getParameters(); ++ int i = 0; ++ for (TypeProjection projection : type.getArguments()) { ++ TypeParameterDescriptor typeParameter = typeParameters.get(i); ++ JetType newArgument = substituteType(projection.getType(), substitution, typeParameter.getVariance()); ++ newArguments.add(new TypeProjection(Variance.INVARIANT, newArgument)); ++ i++; ++ } ++ return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), ++ type.isNullable(), newArguments, type.getMemberScope()); ++ } ++ ++ private static boolean containsType(JetType outer, JetType inner) { ++ if (outer.equals(inner)) { ++ return true; ++ } ++ ++ for (TypeProjection projection : outer.getArguments()) { ++ if (containsType(projection.getType(), inner)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @NotNull ++ private static String renderDescriptor( ++ @NotNull DeclarationDescriptor declarationDescriptor, ++ @NotNull Map typeParameterNameMap, ++ boolean fq ++ ) { ++ if (declarationDescriptor instanceof TypeParameterDescriptor) { ++ String replacement = typeParameterNameMap.get(declarationDescriptor); ++ return replacement == null ? declarationDescriptor.getName().getName() : replacement; ++ } else { ++ return fq ? DescriptorUtils.getFQName(declarationDescriptor).getFqName() : declarationDescriptor.getName().getName(); ++ } ++ } ++ ++ @NotNull ++ private static String renderDescriptor(@NotNull DeclarationDescriptor declarationDescriptor, boolean fq) { ++ return renderDescriptor(declarationDescriptor, Collections.emptyMap(), fq); ++ } ++ ++ private static String renderType(@NotNull JetType type, @NotNull Map typeParameterNameMap, boolean fq) { ++ List projections = type.getArguments(); ++ DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); ++ assert declarationDescriptor != null; ++ if (projections.isEmpty()) { ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq); ++ } ++ ++ List arguments = new ArrayList(); ++ for (TypeProjection projection : projections) { ++ arguments.add(renderType(projection.getType(), typeParameterNameMap, fq)); ++ } ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq) + ""<"" + StringUtil.join(arguments, "", "") + "">""; ++ } ++ ++ @NotNull ++ private static String renderTypeShort(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, false); ++ } ++ ++ @NotNull ++ private static String renderTypeLong(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, true); ++ } ++ ++ @NotNull ++ private static TypeParameterDescriptor[] getTypeParameterNamesNotInScope( ++ @NotNull Collection typeParameters, ++ @NotNull JetScope scope ++ ) { ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ ClassifierDescriptor classifier = scope.getClassifier(typeParameter.getName()); ++ if (classifier == null || !classifier.equals(typeParameter)) { ++ typeParameterNames.add(typeParameter); ++ } ++ } ++ return typeParameterNames.toArray(new TypeParameterDescriptor[typeParameterNames.size()]); ++ } ++ ++ @NotNull ++ private static Set getTypeParametersInType(@NotNull JetType type) { ++ Set typeParameters = new LinkedHashSet(); ++ List arguments = type.getArguments(); ++ if (arguments.isEmpty()) { ++ ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); ++ if (descriptor instanceof TypeParameterDescriptor) { ++ typeParameters.add((TypeParameterDescriptor) descriptor); ++ } ++ } else { ++ for (TypeProjection projection : arguments) { ++ typeParameters.addAll(getTypeParametersInType(projection.getType())); ++ } ++ } ++ return typeParameters; ++ } ++ ++ @NotNull ++ private static String getNextAvailableName(@NotNull String name, @NotNull Collection existingNames) { ++ if (existingNames.contains(name)) { ++ int j = 1; ++ while (existingNames.contains(name + j)) j++; ++ name += j; ++ } ++ return name; ++ } ++ ++ @NotNull ++ private static String getNextAvailableName(@NotNull String name, @NotNull Collection existingNames, @NotNull JetScope scope) { ++ if (existingNames.contains(name) || scope.getClassifier(Name.identifier(name)) != null) { ++ int j = 1; ++ while (existingNames.contains(name + j) || scope.getClassifier(Name.identifier(name + j)) != null) j++; ++ name += j; ++ } ++ return name; ++ } ++ ++ @NotNull ++ private static JetType[] guessTypeForExpression(@NotNull JetExpression expr, @NotNull BindingContext context) { ++ JetType type = context.get(BindingContext.EXPRESSION_TYPE, expr); ++ JetNamedDeclaration declaration = null; ++ ++ // if we know the actual type of the expression ++ if (type != null) { ++ return new JetType[] {type}; ++ } ++ ++ // expression has an expected type ++ else if ((type = context.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expr)) != null) { ++ return new JetType[] {type}; ++ } ++ ++ // expression itself is a type assertion ++ else if (expr instanceof JetTypeConstraint) { // expression itself is a type assertion ++ JetTypeConstraint constraint = (JetTypeConstraint) expr; ++ return new JetType[] {context.get(BindingContext.TYPE, constraint.getBoundTypeReference())}; ++ } ++ ++ // expression is on the left side of a type assertion ++ else if (expr.getParent() instanceof JetTypeConstraint) { ++ JetTypeConstraint constraint = (JetTypeConstraint) expr.getParent(); ++ return new JetType[] {context.get(BindingContext.TYPE, constraint.getBoundTypeReference())}; ++ } ++ ++ // expression is on the lhs of a multi-declaration ++ else if (expr instanceof JetMultiDeclarationEntry) { ++ JetMultiDeclarationEntry entry = (JetMultiDeclarationEntry) expr; ++ JetTypeReference typeRef = entry.getTypeRef(); ++ if (typeRef != null) { // and has a specified type ++ return new JetType[] {context.get(BindingContext.TYPE, typeRef)};","Why not just guess by declaration immediately, without checking `BindingContext.TYPE`? Wouldn't it be enough? +",2013-04-26 11:58:54 +75,"@@ -0,0 +1,1391 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.lookup.LookupElement; ++import com.intellij.codeInsight.lookup.LookupElementBuilder; ++import com.intellij.codeInsight.template.*; ++import com.intellij.codeInsight.template.impl.TemplateImpl; ++import com.intellij.codeInsight.template.impl.Variable; ++import com.intellij.ide.fileTemplates.FileTemplate; ++import com.intellij.ide.fileTemplates.FileTemplateManager; ++import com.intellij.ide.util.PsiElementListCellRenderer; ++import com.intellij.openapi.application.ApplicationManager; ++import com.intellij.openapi.command.CommandProcessor; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.progress.ProcessCanceledException; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.ui.popup.PopupChooserBuilder; ++import com.intellij.openapi.util.TextRange; ++import com.intellij.openapi.util.text.StringUtil; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.psi.search.SearchScope; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.psi.SearchUtils; ++import com.intellij.ui.components.JBList; ++import com.intellij.util.ArrayUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NonNls; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.BindingContextUtils; ++import org.jetbrains.jet.lang.resolve.DescriptorUtils; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.resolve.scopes.JetScope; ++import org.jetbrains.jet.lang.types.*; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening; ++import org.jetbrains.jet.plugin.presentation.JetLightClassListCellRenderer; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; ++import org.jetbrains.jet.plugin.refactoring.JetNameValidator; ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import javax.swing.*; ++import java.util.*; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class CreateMethodFromUsageFix extends CreateFromUsageFixBase { ++ private static final String TYPE_PARAMETER_LIST_VARIABLE_NAME = ""typeParameterList""; ++ private static final String TEMPLATE_FROM_USAGE_METHOD_BODY = ""New Kotlin Method Body.kt""; ++ private static final Pattern COMPONENT_FUNCTION_PATTERN = Pattern.compile(""^component(\\d+)$""); ++ ++ /** ++ * Represents a single choice for a type (e.g. parameter type or return type). ++ */ ++ private static class TypeCandidate { ++ private final JetType type; ++ private final TypeParameterDescriptor[] typeParameters; ++ private String renderedType; ++ private String[] typeParameterNames; ++ ++ public TypeCandidate(@NotNull JetType type) { ++ this.type = type; ++ Set typeParametersInType = getTypeParametersInType(type); ++ typeParameters = typeParametersInType.toArray(new TypeParameterDescriptor[typeParametersInType.size()]); ++ renderedType = renderTypeShort(type, Collections.emptyMap()); ++ } ++ ++ public TypeCandidate(@NotNull JetType type, @NotNull JetScope scope) { ++ this.type = type; ++ typeParameters = getTypeParameterNamesNotInScope(getTypeParametersInType(type), scope); ++ } ++ ++ public void render(@NotNull Map typeParameterNameMap) { ++ renderedType = renderTypeShort(type, typeParameterNameMap); ++ typeParameterNames = new String[typeParameters.length]; ++ int i = 0; ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames[i] = typeParameterNameMap.get(typeParameter); ++ i++; ++ } ++ } ++ ++ @NotNull JetType getType() { ++ return type; ++ } ++ ++ @NotNull ++ public String getRenderedType() { ++ assert renderedType != null : ""call render() first""; ++ return renderedType; ++ } ++ ++ @NotNull ++ public String[] getTypeParameterNames() { ++ assert typeParameterNames != null : ""call render() first""; ++ return typeParameterNames; ++ } ++ ++ @NotNull ++ public TypeParameterDescriptor[] getTypeParameters() { ++ return typeParameters; ++ } ++ } ++ ++ /** ++ * Represents a concrete type or a set of types yet to be inferred from an expression. ++ */ ++ private static class TypeOrExpressionThereof { ++ private final JetExpression expressionOfType; ++ private final JetType type; ++ private final Variance variance; ++ private TypeCandidate[] typeCandidates; ++ private String[] cachedNameCandidatesFromExpression; ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType) { ++ this(expressionOfType, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetExpression expressionOfType, Variance variance) { ++ this(expressionOfType, null, variance); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type) { ++ this(type, Variance.IN_VARIANCE); ++ } ++ ++ public TypeOrExpressionThereof(@NotNull JetType type, Variance variance) { ++ this(null, type, variance); ++ } ++ ++ private TypeOrExpressionThereof(@Nullable JetExpression expressionOfType, @Nullable JetType type, Variance variance) { ++ this.expressionOfType = expressionOfType; ++ this.type = type; ++ this.variance = variance; ++ } ++ ++ public boolean isType() { ++ return this.type != null; ++ } ++ ++ @NotNull ++ public JetType getType() { ++ assert this.type != null; ++ return this.type; ++ } ++ ++ @NotNull ++ private List getPossibleTypes(BindingContext context) { ++ List types = new ArrayList(); ++ if (isType()) { ++ assert type != null : ""!isType() means type == null && expressionOfType != null""; ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ for (JetType type : guessTypeForExpression(expressionOfType, context)) { ++ types.add(type); ++ if (variance == Variance.IN_VARIANCE) { ++ types.addAll(TypeUtils.getAllSupertypes(type)); ++ } ++ } ++ } ++ return types; ++ } ++ ++ public void computeTypeCandidates(@NotNull BindingContext context) { ++ Collection types = getPossibleTypes(context); ++ ++ typeCandidates = new TypeCandidate[types.size()]; ++ int i = 0; ++ for (JetType type : types) { ++ typeCandidates[i] = new TypeCandidate(type); ++ i++; ++ } ++ } ++ ++ public void computeTypeCandidates( ++ @NotNull BindingContext context, ++ @NotNull TypeSubstitution[] substitutions, ++ @NotNull JetScope scope ++ ) { ++ List types = getPossibleTypes(context); ++ Collections.reverse(types); // reverse and reverse back later, so that things added below are added at the front ++ ++ Set newTypes = new LinkedHashSet(types); ++ for (TypeSubstitution substitution : substitutions) { // each substitution can be applied or not, so we offer all options ++ List toAdd = new ArrayList(); ++ List toRemove = new ArrayList(); ++ for (JetType type : newTypes) { ++ toAdd.add(substituteType(type, substitution, variance)); ++ // substitution.byType are type arguments, but they cannot already occur in the type before substitution ++ if (containsType(type, substitution.getByType())) { ++ toRemove.add(type); ++ } ++ } ++ newTypes.addAll(toAdd); ++ newTypes.removeAll(toRemove); ++ } ++ ++ if (newTypes.isEmpty()) { ++ newTypes.add(KotlinBuiltIns.getInstance().getAnyType()); ++ } ++ ++ typeCandidates = new TypeCandidate[newTypes.size()]; ++ int i = typeCandidates.length - 1; // reverse order (see explanation above) ++ for (JetType type : newTypes) { ++ typeCandidates[i] = new TypeCandidate(type, scope); ++ i--; ++ } ++ } ++ ++ @NotNull ++ public TypeCandidate[] getTypeCandidates() { ++ assert typeCandidates != null : ""call computeTypeCandidates() first""; ++ return typeCandidates; ++ } ++ ++ public void renderTypeCandidates(@NotNull Map typeParameterNameMap) { ++ for (TypeCandidate candidate : typeCandidates) { ++ candidate.render(typeParameterNameMap); ++ } ++ } ++ ++ @NotNull ++ public String[] getPossibleNamesFromExpression() { ++ if (cachedNameCandidatesFromExpression != null) return cachedNameCandidatesFromExpression; ++ if (isType()) { ++ cachedNameCandidatesFromExpression = ArrayUtil.EMPTY_STRING_ARRAY; ++ } else { ++ assert expressionOfType != null : ""!isType() means type == null && expressionOfType != null""; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(expressionOfType.getProject()); ++ cachedNameCandidatesFromExpression = JetNameSuggester.suggestNamesForExpression(expressionOfType, dummyValidator); ++ } ++ return cachedNameCandidatesFromExpression; ++ } ++ } ++ ++ /** ++ * Encapsulates information about a method parameter that is going to be created. ++ */ ++ private static class Parameter { ++ private final String preferredName; ++ private final TypeOrExpressionThereof type; ++ ++ public Parameter(@Nullable(""no preferred name"") String preferredName, TypeOrExpressionThereof type) { ++ this.preferredName = preferredName; ++ this.type = type; ++ } ++ ++ public String getPreferredName() { ++ return preferredName; ++ } ++ ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ } ++ ++ /** ++ * Special Expression for parameter names based on its type. ++ */ ++ private static class ParameterNameExpression extends Expression { ++ private final String[] names; ++ private final Map parameterTypeToNamesMap; ++ ++ public ParameterNameExpression(@NotNull String[] names, @NotNull Map parameterTypeToNamesMap) { ++ for (String name : names) { ++ assert name != null && !name.isEmpty(); ++ } ++ this.names = names; ++ this.parameterTypeToNamesMap = parameterTypeToNamesMap; ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ Set names = new LinkedHashSet(); ++ Collections.addAll(names, this.names); ++ ++ // find the parameter list ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) return new LookupElement[0]; ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // add names based on selected type ++ JetParameter parameter = PsiTreeUtil.getParentOfType(elementAt, JetParameter.class); ++ if (parameter != null) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] suggestedNamesBasedOnType = parameterTypeToNamesMap.get(parameterTypeRef.getText()); ++ if (suggestedNamesBasedOnType != null) { ++ Collections.addAll(names, suggestedNamesBasedOnType); ++ } ++ } ++ } ++ ++ // remember other parameter names for later use ++ Set parameterNames = new HashSet(); ++ for (JetParameter jetParameter : parameterList.getParameters()) { ++ if (jetParameter == parameter || jetParameter.getName() == null) continue; ++ parameterNames.add(jetParameter.getName()); ++ } ++ ++ // add fallback parameter name ++ if (names.isEmpty()) { ++ names.add(""arg""); ++ } ++ ++ // ensure there are no conflicts ++ List lookupElements = new ArrayList(); ++ for (String name : names) { ++ name = getNextAvailableName(name, parameterNames); ++ lookupElements.add(LookupElementBuilder.create(name)); ++ } ++ ++ // create and return ++ return lookupElements.toArray(new LookupElement[lookupElements.size()]); ++ } ++ } ++ ++ /** ++ * An Expression for type references. ++ */ ++ private static class TypeExpression extends Expression { ++ private final TypeOrExpressionThereof type; ++ private @NotNull LookupElement[] cachedLookupElements; ++ ++ public TypeExpression(@NotNull TypeOrExpressionThereof type) { ++ this.type = type; ++ TypeCandidate[] candidates = type.getTypeCandidates(); ++ cachedLookupElements = new LookupElement[candidates.length]; ++ for (int i = 0; i < candidates.length; i++) { ++ cachedLookupElements[i] = LookupElementBuilder.create(candidates[i], candidates[i].getRenderedType()); ++ } ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ LookupElement[] lookupItems = calculateLookupItems(context); ++ if (lookupItems.length == 0) return new TextResult(""""); ++ ++ return new TextResult(lookupItems[0].getLookupString()); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return cachedLookupElements; ++ } ++ ++ @NotNull ++ public TypeOrExpressionThereof getType() { ++ return type; ++ } ++ ++ @Nullable(""can't be found"") ++ public JetType getTypeFromSelection(@NotNull String selection) { ++ TypeCandidate[] options = type.getTypeCandidates(); ++ for (TypeCandidate option : options) { ++ if (option.getRenderedType().equals(selection)) { ++ return option.getType(); ++ } ++ } ++ return null; ++ } ++ } ++ ++ /** ++ * A sort-of dummy Expression for parameter lists, to allow us to update the parameter list as the user makes selections. ++ */ ++ private static class TypeParameterListExpression extends Expression { ++ private final String[] typeParameterNamesFromReceiverType; ++ private final Map parameterTypeToTypeParameterNamesMap; ++ ++ public TypeParameterListExpression( ++ @NotNull String[] typeParameterNamesFromReceiverType, ++ @NotNull Map typeParametersMap ++ ) { ++ this.typeParameterNamesFromReceiverType = typeParameterNamesFromReceiverType; ++ this.parameterTypeToTypeParameterNamesMap = typeParametersMap; ++ } ++ ++ @NotNull ++ @Override ++ public Result calculateResult(ExpressionContext context) { ++ Project project = context.getProject(); ++ int offset = context.getStartOffset(); ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ Editor editor = context.getEditor(); ++ assert editor != null; ++ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); ++ assert file != null && file instanceof JetFile; ++ PsiElement elementAt = file.findElementAt(offset); ++ JetFunction func = PsiTreeUtil.getParentOfType(elementAt, JetFunction.class); ++ if (func == null) { ++ return new TextResult(""""); ++ } ++ List parameters = func.getValueParameters(); ++ ++ Set typeParameterNames = new LinkedHashSet(); ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReceiverType); ++ for (JetParameter parameter : parameters) { ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ String[] typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap.get(parameterTypeRef.getText()); ++ if (typeParameterNamesFromParameter != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromParameter); ++ } ++ } ++ } ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ String[] typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap.get(returnTypeRef.getText()); ++ if (typeParameterNamesFromReturnType != null) { ++ Collections.addAll(typeParameterNames, typeParameterNamesFromReturnType); ++ } ++ } ++ ++ return typeParameterNames.isEmpty() ++ ? new TextResult("""") ++ : new TextResult("" <"" + StringUtil.join(typeParameterNames, "", "") + "">""); ++ } ++ ++ @Nullable ++ @Override ++ public Result calculateQuickResult(ExpressionContext context) { ++ return calculateResult(context); ++ } ++ ++ @NotNull ++ @Override ++ public LookupElement[] calculateLookupItems(ExpressionContext context) { ++ return new LookupElement[0]; // do not offer the user any choices ++ } ++ } ++ ++ /** ++ * A JetNameValidator that always succeeds. ++ */ ++ private static class DummyJetNameValidator implements JetNameValidator { ++ private final Project project; ++ ++ public DummyJetNameValidator(Project project) { ++ this.project = project; ++ } ++ ++ @Nullable ++ @Override ++ public String validateName(String name) { ++ return name; ++ } ++ ++ @Override ++ public Project getProject() { ++ return project; ++ } ++ } ++ ++ /** ++ * Encapsulates a single type substitution of a JetType by another JetType. ++ */ ++ private static class TypeSubstitution { ++ private final JetType forType; ++ private final JetType byType; ++ ++ private TypeSubstitution(JetType forType, JetType byType) { ++ this.forType = forType; ++ this.byType = byType; ++ } ++ ++ private JetType getForType() { ++ return forType; ++ } ++ ++ private JetType getByType() { ++ return byType; ++ } ++ } ++ ++ private final String methodName; ++ private final TypeOrExpressionThereof ownerType; ++ private final TypeOrExpressionThereof returnType; ++ private final List parameters; ++ ++ private boolean isUnit; ++ private boolean isExtension; ++ private JetFile currentFile; ++ private JetFile containingFile; ++ private Editor currentFileEditor; ++ private Editor containingFileEditor; ++ private BindingContext currentFileContext; ++ private JetClass ownerClass; ++ private ClassDescriptor ownerClassDescriptor; ++ private TypeCandidate selectedReceiverType; ++ private Map typeParameterNameMap; ++ ++ public CreateMethodFromUsageFix(@NotNull PsiElement element, @NotNull TypeOrExpressionThereof ownerType, @NotNull String methodName, ++ @NotNull TypeOrExpressionThereof returnType, @NotNull List parameters) { ++ super(element); ++ this.methodName = methodName; ++ this.ownerType = ownerType; ++ this.returnType = returnType; ++ this.parameters = parameters; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.method.from.usage"", methodName); ++ } ++ ++ @Override ++ public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ assert file != null && file instanceof JetFile; ++ currentFile = (JetFile) file; ++ currentFileEditor = editor; ++ currentFileContext = AnalyzerFacadeWithCache.analyzeFileWithCache(currentFile).getBindingContext(); ++ ++ ownerType.computeTypeCandidates(currentFileContext); ++ TypeCandidate[] ownerTypeCandidates = ownerType.getTypeCandidates(); ++ assert ownerTypeCandidates.length > 0; ++ if (ownerTypeCandidates.length == 1 || ApplicationManager.getApplication().isUnitTestMode()) { ++ selectedReceiverType = ownerTypeCandidates[0]; ++ doInvoke(project); ++ } else { ++ // class selection ++ List options = new ArrayList(); ++ final Map optionToTypeMap = new HashMap(); ++ for (TypeCandidate ownerTypeCandidate : ownerTypeCandidates) { ++ ClassifierDescriptor possibleClassDescriptor = ownerTypeCandidate.getType().getConstructor().getDeclarationDescriptor(); ++ if (possibleClassDescriptor != null) { ++ String className = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(possibleClassDescriptor.getDefaultType()); ++ DeclarationDescriptor namespaceDescriptor = possibleClassDescriptor.getContainingDeclaration(); ++ String namespace = renderDescriptor(namespaceDescriptor, true); ++ String option = className + "" ("" + namespace + "")""; ++ options.add(option); ++ optionToTypeMap.put(option, ownerTypeCandidate); ++ } ++ } ++ ++ final JList list = new JBList(options); ++ PsiElementListCellRenderer renderer = new JetLightClassListCellRenderer(); ++ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++ list.setCellRenderer(renderer); ++ PopupChooserBuilder builder = new PopupChooserBuilder(list); ++ renderer.installSpeedSearch(builder); ++ ++ Runnable runnable = new Runnable() { ++ @Override ++ public void run() { ++ int index = list.getSelectedIndex(); ++ if (index < 0) return; ++ String option = (String) list.getSelectedValue(); ++ selectedReceiverType = optionToTypeMap.get(option); ++ CommandProcessor.getInstance().executeCommand(project, new Runnable() { ++ @Override ++ public void run() { ++ doInvoke(project); ++ } ++ }, getText(), null); ++ } ++ }; ++ ++ builder.setTitle(JetBundle.message(""choose.target.class.or.trait.title"")) ++ .setItemChoosenCallback(runnable) ++ .createPopup() ++ .showInBestPositionFor(currentFileEditor); ++ } ++ } ++ ++ private void doInvoke(@NotNull final Project project) { ++ // gather relevant information ++ ClassifierDescriptor ownerTypeDescriptor = selectedReceiverType.getType().getConstructor().getDeclarationDescriptor(); ++ assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; ++ ownerClassDescriptor = (ClassDescriptor) ownerTypeDescriptor; ++ JetType receiverType = ownerClassDescriptor.getDefaultType(); ++ PsiElement typeDeclaration = BindingContextUtils.classDescriptorToDeclaration(currentFileContext, ownerClassDescriptor); ++ if (typeDeclaration != null && typeDeclaration instanceof JetClass) { ++ ownerClass = (JetClass) typeDeclaration; ++ isExtension = !ownerClass.isWritable(); ++ } else { ++ isExtension = true; ++ } ++ isUnit = returnType.isType() && isUnit(returnType.getType()); ++ ++ JetScope scope; ++ if (isExtension) { ++ NamespaceDescriptor namespaceDescriptor = currentFileContext.get(BindingContext.FILE_TO_NAMESPACE, currentFile); ++ assert namespaceDescriptor != null; ++ scope = namespaceDescriptor.getMemberScope(); ++ } else { ++ assert ownerClassDescriptor instanceof MutableClassDescriptor; ++ scope = ((MutableClassDescriptor) ownerClassDescriptor).getScopeForMemberResolution(); ++ } ++ ++ // figure out type substitutions for type parameters ++ List classTypeParameters = receiverType.getArguments(); ++ List ownerTypeArguments = selectedReceiverType.getType().getArguments(); ++ assert ownerTypeArguments.size() == classTypeParameters.size(); ++ TypeSubstitution[] substitutions = new TypeSubstitution[classTypeParameters.size()]; ++ for (int i = 0; i < substitutions.length; i++) { ++ substitutions[i] = new TypeSubstitution(ownerTypeArguments.get(i).getType(), classTypeParameters.get(i).getType()); ++ } ++ for (Parameter parameter : parameters) { ++ parameter.getType().computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ if (!isUnit) { ++ returnType.computeTypeCandidates(currentFileContext, substitutions, scope); ++ } ++ ++ // now that we have done substitutions, we can throw it away ++ selectedReceiverType = new TypeCandidate(receiverType, scope); ++ ++ // figure out type parameter renames to avoid conflicts ++ typeParameterNameMap = getTypeParameterRenames(scope); ++ for (Parameter parameter : parameters) { ++ parameter.getType().renderTypeCandidates(typeParameterNameMap); ++ } ++ if (!isUnit) { ++ returnType.renderTypeCandidates(typeParameterNameMap); ++ } ++ selectedReceiverType.render(typeParameterNameMap); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ JetNamedFunction func = createFunctionSkeleton(project); ++ buildAndRunTemplate(project, func); ++ } ++ }); ++ } ++ ++ private JetNamedFunction createFunctionSkeleton(@NotNull Project project) { ++ JetNamedFunction func; ++ String[] parameterStrings = new String[parameters.size()]; ++ for (int i = 0; i < parameterStrings.length; i++) { ++ parameterStrings[i] = ""p"" + i + "": Any""; ++ } ++ String parametersString = StringUtil.join(parameterStrings,"", ""); ++ String returnTypeString = isUnit ? """" : "": Any""; ++ if (isExtension) { // create as extension function ++ String ownerTypeString = selectedReceiverType.getRenderedType(); ++ String methodText = String.format(""fun %s.%s(%s)%s { }"", ownerTypeString, methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ containingFile = currentFile; ++ containingFileEditor = currentFileEditor; ++ func = (JetNamedFunction) currentFile.add(func); ++ } else { // create as method ++ String methodText = String.format(""fun %s(%s)%s { }"", methodName, parametersString, returnTypeString); ++ func = JetPsiFactory.createFunction(project, methodText); ++ PsiFile classContainingFile = ownerClass.getContainingFile(); ++ assert classContainingFile instanceof JetFile; ++ containingFile = (JetFile) classContainingFile; ++ ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true); ++ containingFileEditor = fileEditorManager.getSelectedTextEditor(); ++ ++ JetClassBody classBody = ownerClass.getBody(); ++ if (classBody == null) { ++ classBody = (JetClassBody) ownerClass.add(JetPsiFactory.createEmptyClassBody(project)); ++ ownerClass.addBefore(JetPsiFactory.createWhiteSpace(project), classBody); ++ } ++ PsiElement rBrace = classBody.getRBrace(); ++ assert rBrace != null; ++ func = (JetNamedFunction) classBody.addBefore(func, rBrace); ++ } ++ ++ return func; ++ } ++ ++ private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) { ++ JetParameterList parameterList = func.getValueParameterList(); ++ assert parameterList != null; ++ ++ // build templates ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument()); ++ ++ CaretModel caretModel = containingFileEditor.getCaretModel(); ++ caretModel.moveToOffset(containingFile.getNode().getStartOffset()); ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile); ++ final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); ++ final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); ++ ++ // add a segment for the parameter list ++ // Note: because TemplateBuilderImpl does not have a replaceElement overload that takes in both a TextRange and alwaysStopAt, we ++ // need to create the segment first and then hack the Expression into the template later. We use this template to update the type ++ // parameter list as the user makes selections in the parameter types, and we need alwaysStopAt to be false so the user can't tab to ++ // it. ++ TypeParameterListExpression expression = setupTypeParameterListTemplate(builder, func); ++ ++ // the template built by TemplateBuilderImpl is ordered by element position, but we want types to be first, so hack it ++ final TemplateImpl template = (TemplateImpl) builder.buildInlineTemplate(); ++ ArrayList variables = template.getVariables(); ++ for (int i = 0; i < parameters.size(); i++) { ++ Collections.swap(variables, i * 2, i * 2 + 1); ++ } ++ ++ // fix up the template to include the expression for the type parameter list ++ variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); ++ ++ // run the template ++ TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template _, boolean brokenOff) { ++ // file templates ++ int offset = template.getSegmentOffset(0); ++ final JetNamedFunction func = PsiTreeUtil.findElementOfClassAtOffset(containingFile, offset, JetNamedFunction.class, false); ++ assert func != null; ++ final List typeRefsToShorten = new ArrayList(); ++ ++ ApplicationManager.getApplication().runWriteAction(new Runnable() { ++ @Override ++ public void run() { ++ // file templates ++ setupFunctionBody(project, func); ++ ++ // change short type names to fully qualified ones (to be shortened below) ++ setupTypeReferencesForShortening(project, func, typeRefsToShorten, parameterTypeExpressions, returnTypeExpression); ++ } ++ }); ++ ++ ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten); ++ } ++ }); ++ } ++ ++ private Map getTypeParameterRenames(JetScope scope) { ++ TypeParameterDescriptor[] receiverTypeParametersNotInScope = selectedReceiverType.getTypeParameters(); ++ Set allTypeParametersNotInScope = new LinkedHashSet(); ++ allTypeParametersNotInScope.addAll(Arrays.asList(receiverTypeParametersNotInScope)); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(parameterTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ if (!isUnit) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ allTypeParametersNotInScope.addAll(Arrays.asList(returnTypeCandidate.getTypeParameters())); ++ } ++ } ++ ++ List typeParameters = new ArrayList(allTypeParametersNotInScope); ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ typeParameterNames.add(getNextAvailableName(typeParameter.getName().getName(), typeParameterNames, scope)); ++ } ++ assert typeParameters.size() == typeParameterNames.size(); ++ Map typeParameterNameMap = new HashMap(); ++ for (int i = 0; i < typeParameters.size(); i++) { ++ typeParameterNameMap.put(typeParameters.get(i), typeParameterNames.get(i)); ++ } ++ ++ return typeParameterNameMap; ++ } ++ ++ private void setupTypeReferencesForShortening( ++ @NotNull Project project, ++ @NotNull JetNamedFunction func, ++ @NotNull List typeRefsToShorten, ++ @NotNull TypeExpression[] parameterTypeExpressions, ++ @Nullable TypeExpression returnTypeExpression ++ ) { ++ if (isExtension) { ++ JetTypeReference receiverTypeRef = ++ JetPsiFactory.createType(project, renderTypeLong(selectedReceiverType.getType(), typeParameterNameMap)); ++ replaceWithLongerName(project, receiverTypeRef, selectedReceiverType.getType()); ++ ++ receiverTypeRef = func.getReceiverTypeRef(); ++ if (receiverTypeRef != null) { ++ typeRefsToShorten.add(receiverTypeRef); ++ } ++ } ++ ++ if (!isUnit) { ++ assert returnTypeExpression != null; ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ JetType returnType = returnTypeExpression.getTypeFromSelection(returnTypeRef.getText()); ++ if (returnType != null) { // user selected a given type ++ replaceWithLongerName(project, returnTypeRef, returnType); ++ returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ typeRefsToShorten.add(returnTypeRef); ++ } ++ } ++ } ++ ++ List valueParameters = func.getValueParameters(); ++ List parameterIndicesToShorten = new ArrayList(); ++ assert valueParameters.size() == parameterTypeExpressions.length; ++ for (int i = 0; i < valueParameters.size(); i++) { ++ JetParameter parameter = valueParameters.get(i); ++ JetTypeReference parameterTypeRef = parameter.getTypeReference(); ++ if (parameterTypeRef != null) { ++ JetType parameterType = parameterTypeExpressions[i].getTypeFromSelection(parameterTypeRef.getText()); ++ if (parameterType != null) { ++ replaceWithLongerName(project, parameterTypeRef, parameterType); ++ parameterIndicesToShorten.add(i); ++ } ++ } ++ } ++ valueParameters = func.getValueParameters(); ++ for (int i : parameterIndicesToShorten) { ++ JetTypeReference parameterTypeRef = valueParameters.get(i).getTypeReference(); ++ if (parameterTypeRef != null) { ++ typeRefsToShorten.add(parameterTypeRef); ++ } ++ } ++ } ++ ++ private void setupFunctionBody(@NotNull Project project, @NotNull JetNamedFunction func) { ++ FileTemplate fileTemplate = FileTemplateManager.getInstance().getCodeTemplate(TEMPLATE_FROM_USAGE_METHOD_BODY); ++ Properties properties = new Properties(); ++ if (isUnit) { ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, ""Unit""); ++ } else { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnTypeRef.getText()); ++ } ++ properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFQName(ownerClassDescriptor).getFqName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, ownerClassDescriptor.getName().getName()); ++ properties.setProperty(FileTemplate.ATTRIBUTE_METHOD_NAME, methodName); ++ ++ @NonNls String bodyText; ++ try { ++ bodyText = fileTemplate.getText(properties); ++ } catch (ProcessCanceledException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IncorrectOperationException(""Failed to parse file template"", e); ++ } ++ JetExpression newBodyExpression = JetPsiFactory.createFunctionBody(project, bodyText); ++ JetExpression oldBodyExpression = func.getBodyExpression(); ++ assert oldBodyExpression != null; ++ oldBodyExpression.replace(newBodyExpression); ++ } ++ ++ @NotNull ++ private TypeExpression setupReturnTypeTemplate(@NotNull TemplateBuilder builder, @NotNull JetNamedFunction func) { ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ assert returnTypeRef != null; ++ TypeExpression returnTypeExpression = new TypeExpression(returnType); ++ builder.replaceElement(returnTypeRef, returnTypeExpression); ++ return returnTypeExpression; ++ } ++ ++ @NotNull ++ private TypeParameterListExpression setupTypeParameterListTemplate(@NotNull TemplateBuilderImpl builder, @NotNull JetNamedFunction func) { ++ Map typeParameterMap = new HashMap(); ++ String[] receiverTypeParameterNames = selectedReceiverType.getTypeParameterNames(); ++ ++ for (Parameter parameter : parameters) { ++ TypeCandidate[] parameterTypeCandidates = parameter.getType().getTypeCandidates(); ++ for (TypeCandidate parameterTypeCandidate : parameterTypeCandidates) { ++ typeParameterMap.put(parameterTypeCandidate.getRenderedType(), parameterTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ JetTypeReference returnTypeRef = func.getReturnTypeRef(); ++ if (returnTypeRef != null) { ++ TypeCandidate[] returnTypeCandidates = returnType.getTypeCandidates(); ++ for (TypeCandidate returnTypeCandidate : returnTypeCandidates) { ++ typeParameterMap.put(returnTypeCandidate.getRenderedType(), returnTypeCandidate.getTypeParameterNames()); ++ } ++ } ++ ++ builder.replaceElement(func, TextRange.create(3, 3), TYPE_PARAMETER_LIST_VARIABLE_NAME, null, false); // ((3, 3) is after ""fun"") ++ return new TypeParameterListExpression(receiverTypeParameterNames, typeParameterMap); ++ } ++ ++ private TypeExpression[] setupParameterTypeTemplates(@NotNull Project project, @NotNull TemplateBuilder builder, ++ @NotNull JetParameterList parameterList) { ++ List jetParameters = parameterList.getParameters(); ++ assert jetParameters.size() == parameters.size(); ++ TypeExpression[] parameterTypeExpressions = new TypeExpression[parameters.size()]; ++ JetNameValidator dummyValidator = new DummyJetNameValidator(project); ++ for (int i = 0; i < parameters.size(); i++) { ++ Parameter parameter = parameters.get(i); ++ JetParameter jetParameter = jetParameters.get(i); ++ ++ // add parameter type to the template ++ parameterTypeExpressions[i] = new TypeExpression(parameter.getType()); ++ JetTypeReference parameterTypeRef = jetParameter.getTypeReference(); ++ assert parameterTypeRef != null; ++ builder.replaceElement(parameterTypeRef, parameterTypeExpressions[i]); ++ ++ // add parameter name to the template ++ String[] possibleNamesFromExpression = parameter.getType().getPossibleNamesFromExpression(); ++ String preferredName = parameter.getPreferredName(); ++ String[] possibleNames; ++ if (preferredName != null) { ++ possibleNames = new String[possibleNamesFromExpression.length + 1]; ++ possibleNames[0] = preferredName; ++ System.arraycopy(possibleNamesFromExpression, 0, possibleNames, 1, possibleNamesFromExpression.length); ++ } else { ++ possibleNames = possibleNamesFromExpression; ++ } ++ ++ // figure out suggested names for each type option ++ Map parameterTypeToNamesMap = new HashMap(); ++ for (TypeCandidate typeCandidate : parameter.getType().getTypeCandidates()) { ++ String[] suggestedNames = JetNameSuggester.suggestNamesForType(typeCandidate.getType(), dummyValidator); ++ parameterTypeToNamesMap.put(typeCandidate.getRenderedType(), suggestedNames); ++ } ++ ++ // add expression to builder ++ Expression parameterNameExpression = new ParameterNameExpression(possibleNames, parameterTypeToNamesMap); ++ PsiElement parameterNameIdentifier = jetParameter.getNameIdentifier(); ++ assert parameterNameIdentifier != null; ++ builder.replaceElement(parameterNameIdentifier, parameterNameExpression); ++ } ++ return parameterTypeExpressions; ++ } ++ ++ private void replaceWithLongerName(@NotNull Project project, @NotNull JetTypeReference typeRef, @NotNull JetType type) { ++ JetTypeReference fullyQualifiedReceiverTypeRef = JetPsiFactory.createType(project, renderTypeLong(type, typeParameterNameMap)); ++ typeRef.replace(fullyQualifiedReceiverTypeRef); ++ } ++ ++ @NotNull ++ private static JetType substituteType(@NotNull JetType type, @NotNull TypeSubstitution substitution, @NotNull Variance variance) { ++ switch (variance) { ++ case INVARIANT: ++ // for invariant, can replace only when they're equal ++ if (type.equals(substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case IN_VARIANCE: ++ // for covariant (e.g. function parameter), can replace type with any of its supertypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(type, substitution.getForType())) { ++ return substitution.getByType(); ++ } ++ break; ++ case OUT_VARIANCE: ++ // for contravariant (e.g. function return value), can replace type with any of its subtypes ++ if (JetTypeChecker.INSTANCE.isSubtypeOf(substitution.getForType(), type)) { ++ return substitution.getByType(); ++ } ++ break; ++ } ++ ++ List newArguments = new ArrayList(); ++ List typeParameters = type.getConstructor().getParameters(); ++ int i = 0; ++ for (TypeProjection projection : type.getArguments()) { ++ TypeParameterDescriptor typeParameter = typeParameters.get(i); ++ JetType newArgument = substituteType(projection.getType(), substitution, typeParameter.getVariance()); ++ newArguments.add(new TypeProjection(Variance.INVARIANT, newArgument)); ++ i++; ++ } ++ return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), ++ type.isNullable(), newArguments, type.getMemberScope()); ++ } ++ ++ private static boolean containsType(JetType outer, JetType inner) { ++ if (outer.equals(inner)) { ++ return true; ++ } ++ ++ for (TypeProjection projection : outer.getArguments()) { ++ if (containsType(projection.getType(), inner)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @NotNull ++ private static String renderDescriptor( ++ @NotNull DeclarationDescriptor declarationDescriptor, ++ @NotNull Map typeParameterNameMap, ++ boolean fq ++ ) { ++ if (declarationDescriptor instanceof TypeParameterDescriptor) { ++ String replacement = typeParameterNameMap.get(declarationDescriptor); ++ return replacement == null ? declarationDescriptor.getName().getName() : replacement; ++ } else { ++ return fq ? DescriptorUtils.getFQName(declarationDescriptor).getFqName() : declarationDescriptor.getName().getName(); ++ } ++ } ++ ++ @NotNull ++ private static String renderDescriptor(@NotNull DeclarationDescriptor declarationDescriptor, boolean fq) { ++ return renderDescriptor(declarationDescriptor, Collections.emptyMap(), fq); ++ } ++ ++ private static String renderType(@NotNull JetType type, @NotNull Map typeParameterNameMap, boolean fq) { ++ List projections = type.getArguments(); ++ DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); ++ assert declarationDescriptor != null; ++ if (projections.isEmpty()) { ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq); ++ } ++ ++ List arguments = new ArrayList(); ++ for (TypeProjection projection : projections) { ++ arguments.add(renderType(projection.getType(), typeParameterNameMap, fq)); ++ } ++ return renderDescriptor(declarationDescriptor, typeParameterNameMap, fq) + ""<"" + StringUtil.join(arguments, "", "") + "">""; ++ } ++ ++ @NotNull ++ private static String renderTypeShort(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, false); ++ } ++ ++ @NotNull ++ private static String renderTypeLong(@NotNull JetType type, @NotNull Map typeParameterNameMap) { ++ return renderType(type, typeParameterNameMap, true); ++ } ++ ++ @NotNull ++ private static TypeParameterDescriptor[] getTypeParameterNamesNotInScope( ++ @NotNull Collection typeParameters, ++ @NotNull JetScope scope ++ ) { ++ List typeParameterNames = new ArrayList(); ++ for (TypeParameterDescriptor typeParameter : typeParameters) { ++ ClassifierDescriptor classifier = scope.getClassifier(typeParameter.getName()); ++ if (classifier == null || !classifier.equals(typeParameter)) { ++ typeParameterNames.add(typeParameter); ++ } ++ } ++ return typeParameterNames.toArray(new TypeParameterDescriptor[typeParameterNames.size()]); ++ } ++ ++ @NotNull ++ private static Set getTypeParametersInType(@NotNull JetType type) { ++ Set typeParameters = new LinkedHashSet(); ++ List arguments = type.getArguments(); ++ if (arguments.isEmpty()) { ++ ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); ++ if (descriptor instanceof TypeParameterDescriptor) { ++ typeParameters.add((TypeParameterDescriptor) descriptor); ++ } ++ } else { ++ for (TypeProjection projection : arguments) { ++ typeParameters.addAll(getTypeParametersInType(projection.getType())); ++ } ++ } ++ return typeParameters; ++ } ++ ++ @NotNull ++ private static String getNextAvailableName(@NotNull String name, @NotNull Collection existingNames) { ++ if (existingNames.contains(name)) { ++ int j = 1; ++ while (existingNames.contains(name + j)) j++; ++ name += j; ++ } ++ return name; ++ } ++ ++ @NotNull ++ private static String getNextAvailableName(@NotNull String name, @NotNull Collection existingNames, @NotNull JetScope scope) { ++ if (existingNames.contains(name) || scope.getClassifier(Name.identifier(name)) != null) { ++ int j = 1; ++ while (existingNames.contains(name + j) || scope.getClassifier(Name.identifier(name + j)) != null) j++; ++ name += j; ++ } ++ return name; ++ } ++ ++ @NotNull ++ private static JetType[] guessTypeForExpression(@NotNull JetExpression expr, @NotNull BindingContext context) { ++ JetType type = context.get(BindingContext.EXPRESSION_TYPE, expr); ++ JetNamedDeclaration declaration = null; ++ ++ // if we know the actual type of the expression ++ if (type != null) { ++ return new JetType[] {type}; ++ } ++ ++ // expression has an expected type ++ else if ((type = context.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expr)) != null) { ++ return new JetType[] {type}; ++ } ++ ++ // expression itself is a type assertion ++ else if (expr instanceof JetTypeConstraint) { // expression itself is a type assertion ++ JetTypeConstraint constraint = (JetTypeConstraint) expr; ++ return new JetType[] {context.get(BindingContext.TYPE, constraint.getBoundTypeReference())}; ++ } ++ ++ // expression is on the left side of a type assertion ++ else if (expr.getParent() instanceof JetTypeConstraint) { ++ JetTypeConstraint constraint = (JetTypeConstraint) expr.getParent(); ++ return new JetType[] {context.get(BindingContext.TYPE, constraint.getBoundTypeReference())}; ++ } ++ ++ // expression is on the lhs of a multi-declaration ++ else if (expr instanceof JetMultiDeclarationEntry) { ++ JetMultiDeclarationEntry entry = (JetMultiDeclarationEntry) expr; ++ JetTypeReference typeRef = entry.getTypeRef(); ++ if (typeRef != null) { // and has a specified type ++ return new JetType[] {context.get(BindingContext.TYPE, typeRef)}; ++ } ++ declaration = entry; // otherwise fall through and guess ++ } ++ ++ // expression is a parameter (e.g. declared in a for-loop) ++ else if (expr instanceof JetParameter) { ++ JetParameter parameter = (JetParameter) expr; ++ JetTypeReference typeRef = parameter.getTypeReference(); ++ if (typeRef != null) { // and has a specified type ++ return new JetType[] {context.get(BindingContext.TYPE, typeRef)}; ++ } ++ declaration = parameter; // otherwise fall through and guess ++ } ++ ++ // the expression is the RHS of a variable assignment with a specified type ++ else if (expr.getParent() instanceof JetVariableDeclaration) { ++ JetVariableDeclaration variable = (JetVariableDeclaration) expr.getParent(); ++ JetTypeReference typeRef = variable.getTypeRef(); ++ if (typeRef != null) { // and has a specified type ++ return new JetType[] {context.get(BindingContext.TYPE, typeRef)}; ++ } ++ declaration = variable; // otherwise fall through and guess, based on LHS ++ } ++ ++ // guess based on declaration ++ SearchScope scope = expr.getContainingFile().getUseScope(); ++ Set expectedTypes = new HashSet(); ++ if (declaration != null) { ++ for (PsiReference ref : SearchUtils.findAllReferences(declaration, scope)) { ++ if (ref instanceof JetSimpleNameReference) { ++ JetSimpleNameReference simpleNameRef = (JetSimpleNameReference) ref; ++ JetType expectedType = context.get(BindingContext.EXPECTED_EXPRESSION_TYPE, simpleNameRef.getExpression()); ++ if (expectedType != null) { ++ expectedTypes.add(expectedType); ++ } ++ } ++ } ++ } ++ if (expectedTypes.isEmpty()) { ++ return new JetType[0]; ++ } ++ type = TypeUtils.intersect(JetTypeChecker.INSTANCE, expectedTypes); ++ if (type != null) { ++ return new JetType[] {type}; ++ } else { // intersection doesn't exist; let user make an imperfect choice ++ return expectedTypes.toArray(new JetType[expectedTypes.size()]); ++ } ++ } ++ ++ private static boolean isUnit(@NotNull JetType type) {","Method is trivial and used once. It's redundant. +",2013-04-26 11:59:27 +862,"@@ -0,0 +1,147 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory ++import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import com.intellij.psi.PsiModifier ++import com.intellij.psi.PsiType ++import org.jetbrains.kotlin.asJava.elements.KtLightElement ++import org.jetbrains.kotlin.builtins.DefaultBuiltIns ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.idea.core.insertMembersAfter ++import org.jetbrains.kotlin.idea.quickfix.AddModifierFix ++import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.platform.JavaToKotlinClassMap ++import org.jetbrains.kotlin.psi.KtClassOrObject ++import org.jetbrains.kotlin.psi.KtElement ++import org.jetbrains.kotlin.psi.KtModifierListOwner ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe ++import org.jetbrains.uast.UClass ++import org.jetbrains.uast.UDeclaration ++import org.jetbrains.uast.UElement ++ ++ ++class KotlinCommonIntentionActionsFactory : JvmCommonIntentionActionsFactory() { ++ override fun createChangeModifierAction(declaration: UDeclaration, modifier: String, shouldPresent: Boolean): IntentionAction? { ++ val kModifierOwner = declaration.asKtElement() ++ ?: throw IllegalArgumentException(""$declaration is expected to contain KtLightElement with KtModifierListOwner"") ++ ++ val (kToken, shouldPresentMapped) = if (PsiModifier.FINAL == modifier) ++ KtTokens.OPEN_KEYWORD to !shouldPresent ++ else ++ javaPsiModifiersMapping[modifier] to shouldPresent ++ ++ if (kToken == null) return null ++ return if (shouldPresentMapped) ++ AddModifierFix.createIfApplicable(kModifierOwner, kToken) ++ else ++ RemoveModifierFix(kModifierOwner, kToken, false) ++ } ++ ++ private inline fun UElement.asKtElement(): T? = ++ (psi as? KtLightElement<*, *>?)?.kotlinOrigin as? T ++ ++ companion object { ++ val javaPsiModifiersMapping = mapOf( ++ PsiModifier.PRIVATE to KtTokens.PRIVATE_KEYWORD, ++ PsiModifier.PUBLIC to KtTokens.PUBLIC_KEYWORD, ++ PsiModifier.PROTECTED to KtTokens.PUBLIC_KEYWORD, ++ PsiModifier.ABSTRACT to KtTokens.ABSTRACT_KEYWORD ++ ) ++ ++ val javaVisibilityMapping: Map = mapOf( ++ PsiModifier.PRIVATE to Visibilities.PRIVATE.displayName, ++ PsiModifier.PUBLIC to """", ++ PsiModifier.PROTECTED to Visibilities.PROTECTED.displayName, ++ PsiModifier.PACKAGE_LOCAL to Visibilities.INTERNAL.displayName ++ ).withDefault { Visibilities.DEFAULT_VISIBILITY.displayName } ++ } ++ ++ override fun createAddMethodAction(uClass: UClass, methodName: String, visibilityModifier: String, returnType: PsiType, vararg parameters: PsiType): IntentionAction? { ++ val returnTypeString: String = typeString(returnType).let { ++ when { ++ it.isEmpty() -> """" ++ else -> "": $it"" ++ } ++ } ++ val paramsStr = parameters.mapIndexed { index, psiType -> ""arg${index + 1}: ${typeString(psiType)}"" }.joinToString() ++ return object : LocalQuickFixAndIntentionActionOnPsiElement(uClass) { ++ override fun getFamilyName(): String = ""Add method"" ++ ++ private val text = ""Add method '$methodName' to '${uClass.name}'"" ++ ++ override fun getText(): String = text ++ ++ override fun invoke(project: Project, file: PsiFile, editor: Editor?, startElement: PsiElement, endElement: PsiElement) { ++ val visibilityStr = javaVisibilityMapping.getValue(visibilityModifier) ++ val psiFactory = KtPsiFactory(uClass) ++ val function = psiFactory.createFunction(""$visibilityStr fun $methodName($paramsStr)$returnTypeString{}"")",You should use `KtPsiFactory.CallableBuilder` instead of building the text manually.,2017-05-23 16:43:17 +861,"@@ -0,0 +1,15 @@ ++// ""Replace with safe (?.) call"" ""false"" ++// ACTION: Add non-null asserted (!!) call ++// ACTION: Convert to expression body ++// ACTION: Replace with safe (this?.) call ++// ACTION: Wrap with '?.let { ... }' call ++// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type A? ++ ++class A { ++ fun foo() { ++ } ++} ++ ++fun A?.bar() { ++ foo() ++}","Why does this test have so strange name? I see no `invoke` here, either safe or unsafe",2017-05-23 12:28:05 +636,"@@ -0,0 +1,15 @@ ++// WITH_RUNTIME ++ ++fun contains(set: Set, x: Int): Boolean = when { ++ set.size == 0 -> false ++ else -> x in set as Set ++} ++ ++fun box(): String { ++ val set = setOf(1) ++ if (contains(set, 1)) { ++ return ""OK"" ++ } ++ ++ return ""Fail"" ++}","This test in not related to Range#contains, but at some point I had implementation which passed all tests (without this one), but ant build was failed. +",2016-10-11 19:02:08 +170,"@@ -0,0 +1,15 @@ ++class TestingUse { ++ fun test(sum: Int.(a: Int) -> Int, b: Int): Int { ++ return b.sum(b) ++ } ++ fun test2(sum: (a: Int, b: Int) -> Int, c: Int): Int {","Basically you've used the same test data file in all tests on `makeTypeExplicitInLambda`, altering the calling function in each case. This is not a good idea, because once one of such tests fails, the investigating person might think that the fact that there are several functions in this file is relevant to the test case, while in reality it's not. + +Please try to make your tests as minimal as possible, i.e. only include relevant data in each test. +",2014-04-09 16:19:26 +840,"@@ -0,0 +1,15 @@ ++data class Foo(val a: String) { ++ fun copy(i: Int) {} ++} ++ ++class Foo2() { ++ fun copy(i: Int) {} ++} ++","I'd add an example that clearly shows all should be named, like this: +``` +data class SomeName(a: Int, b: Int, c: String) +f.copy(2, c = """") +```",2017-05-03 09:49:34 +968,"@@ -0,0 +1,150 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.config.LanguageFeature ++import org.jetbrains.kotlin.config.LanguageVersionSettings ++import org.jetbrains.kotlin.descriptors.ModuleDescriptor ++import org.jetbrains.kotlin.effectsystem.effects.ESCalls ++import org.jetbrains.kotlin.effectsystem.effects.ESReturns ++import org.jetbrains.kotlin.effectsystem.factories.UNKNOWN_CONSTANT ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.resolving.FunctorResolver ++import org.jetbrains.kotlin.effectsystem.structure.ESEffect ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.visitors.Reducer ++import org.jetbrains.kotlin.effectsystem.visitors.SchemaBuilder ++import org.jetbrains.kotlin.psi.KtCallExpression ++import org.jetbrains.kotlin.psi.KtDeclaration ++import org.jetbrains.kotlin.psi.KtExpression ++import org.jetbrains.kotlin.psi.KtLambdaExpression ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory ++ ++class EffectSystem(val languageVersionSettings: LanguageVersionSettings) { ++ private val functorResolver = FunctorResolver() ++ ++ fun getResultDataFlowInfo( ++ resolvedCall: ResolvedCall<*>, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): DataFlowInfo { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractEffects)) return DataFlowInfo.EMPTY ++ ++ // Prevent launch of effect system machinery on pointless cases (constants/enums/constructors/etc.) ++ val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return DataFlowInfo.EMPTY ++ if (callExpression is KtDeclaration) return DataFlowInfo.EMPTY ++ ++ val resultContextInfo = getContextInfoWhen(ESReturns(UNKNOWN_CONSTANT), callExpression, bindingTrace, moduleDescriptor) ++ ++ return resultContextInfo.toDataFlowInfo(languageVersionSettings) ++ } ++ ++ fun recordDefiniteInvocations(resolvedCall: ResolvedCall<*>, bindingTrace: BindingTrace, moduleDescriptor: ModuleDescriptor) {",In this function we have some strange combination of `getResultDataFlowInfo` and `checkAndRecordDefiniteInvocations`. I think some refactoring is needed here.,2017-08-15 15:52:13 +970,"@@ -0,0 +1,150 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.config.LanguageFeature ++import org.jetbrains.kotlin.config.LanguageVersionSettings ++import org.jetbrains.kotlin.descriptors.ModuleDescriptor ++import org.jetbrains.kotlin.effectsystem.effects.ESCalls ++import org.jetbrains.kotlin.effectsystem.effects.ESReturns ++import org.jetbrains.kotlin.effectsystem.factories.UNKNOWN_CONSTANT ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.resolving.FunctorResolver ++import org.jetbrains.kotlin.effectsystem.structure.ESEffect ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.visitors.Reducer ++import org.jetbrains.kotlin.effectsystem.visitors.SchemaBuilder ++import org.jetbrains.kotlin.psi.KtCallExpression ++import org.jetbrains.kotlin.psi.KtDeclaration ++import org.jetbrains.kotlin.psi.KtExpression ++import org.jetbrains.kotlin.psi.KtLambdaExpression ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory ++ ++class EffectSystem(val languageVersionSettings: LanguageVersionSettings) { ++ private val functorResolver = FunctorResolver() ++ ++ fun getResultDataFlowInfo( ++ resolvedCall: ResolvedCall<*>, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): DataFlowInfo { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractEffects)) return DataFlowInfo.EMPTY ++ ++ // Prevent launch of effect system machinery on pointless cases (constants/enums/constructors/etc.) ++ val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return DataFlowInfo.EMPTY ++ if (callExpression is KtDeclaration) return DataFlowInfo.EMPTY ++ ++ val resultContextInfo = getContextInfoWhen(ESReturns(UNKNOWN_CONSTANT), callExpression, bindingTrace, moduleDescriptor) ++ ++ return resultContextInfo.toDataFlowInfo(languageVersionSettings) ++ } ++ ++ fun recordDefiniteInvocations(resolvedCall: ResolvedCall<*>, bindingTrace: BindingTrace, moduleDescriptor: ModuleDescriptor) { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.CalledInPlaceEffect)) return ++ ++ // Prevent launch of effect system machinery on pointless cases (constants/enums/constructors/etc.) ++ val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return ++ if (callExpression is KtDeclaration) return ++ ++ val resultingContextInfo = getContextInfoWhen(ESReturns(UNKNOWN_CONSTANT), callExpression, bindingTrace, moduleDescriptor) ++ for (effect in resultingContextInfo.firedEffects) { ++ val callsEffect = effect as? ESCalls ?: continue ++ val id = callsEffect.callable.id as DataFlowValueID ++ ++ // Could be also IdentifierInfo.Variable when call passes non-anonymous lambda for callable parameter ++ val lambdaExpr = (id.dfv.identifierInfo as? DataFlowValueFactory.ExpressionIdentifierInfo)?.expression ?: continue ++ assert(lambdaExpr is KtLambdaExpression) { ""Unexpected argument of Calls-effect: expected KtLambdaExpression, got $lambdaExpr"" } ++ ++ bindingTrace.record(BindingContext.LAMBDA_INVOCATIONS, lambdaExpr as KtLambdaExpression, callsEffect.kind) ++ } ++ } ++ ++ fun getConditionalInfoForThenBranch( ++ condition: KtExpression?, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): DataFlowInfo { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractEffects)) return DataFlowInfo.EMPTY ++ if (condition == null) return DataFlowInfo.EMPTY ++ ++ return getContextInfoWhen(ESReturns(true.lift()), condition, bindingTrace, moduleDescriptor) ++ .toDataFlowInfo(languageVersionSettings) ++ } ++ ++ fun getConditionalInfoForElseBranch( ++ condition: KtExpression?, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): DataFlowInfo { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractEffects)) return DataFlowInfo.EMPTY ++ if (condition == null) return DataFlowInfo.EMPTY ++ ++ return getContextInfoWhen(ESReturns(false.lift()), condition, bindingTrace, moduleDescriptor) ++ .toDataFlowInfo(languageVersionSettings) ++ } ++ ++ private fun getContextInfoWhen( ++ observedEffect: ESEffect, ++ expression: KtExpression, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): MutableContextInfo { ++ val schema = getSchema(expression, bindingTrace, moduleDescriptor) ?: return MutableContextInfo.EMPTY ++ ++ val extractedContextInfo = InfoCollector(observedEffect).collectFromSchema(schema) ++ ++ return extractedContextInfo ++ } ++ ++ private fun getSchema(expression: KtExpression, bindingTrace: BindingTrace, moduleDescriptor: ModuleDescriptor): EffectSchema? { ++ if (bindingTrace[BindingContext.EXPRESSION_EFFECTS, expression] == null) { ++ val evaluatedSchema = evaluateSchema(expression, bindingTrace.bindingContext, moduleDescriptor) ?: return null ++ bindingTrace.record(BindingContext.EXPRESSION_EFFECTS, expression, evaluatedSchema) ++ } ++ ++ return bindingTrace[BindingContext.EXPRESSION_EFFECTS, expression]",I'd try to avoid repeated access to `bindingTrace` here.,2017-08-15 16:01:33 +982,"@@ -0,0 +1,150 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.config.LanguageFeature ++import org.jetbrains.kotlin.config.LanguageVersionSettings ++import org.jetbrains.kotlin.descriptors.ModuleDescriptor ++import org.jetbrains.kotlin.effectsystem.effects.ESCalls ++import org.jetbrains.kotlin.effectsystem.effects.ESReturns ++import org.jetbrains.kotlin.effectsystem.factories.UNKNOWN_CONSTANT ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.resolving.FunctorResolver ++import org.jetbrains.kotlin.effectsystem.structure.ESEffect ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.visitors.Reducer ++import org.jetbrains.kotlin.effectsystem.visitors.SchemaBuilder ++import org.jetbrains.kotlin.psi.KtCallExpression ++import org.jetbrains.kotlin.psi.KtDeclaration ++import org.jetbrains.kotlin.psi.KtExpression ++import org.jetbrains.kotlin.psi.KtLambdaExpression ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory ++ ++class EffectSystem(val languageVersionSettings: LanguageVersionSettings) { ++ private val functorResolver = FunctorResolver() ++ ++ fun getResultDataFlowInfo( ++ resolvedCall: ResolvedCall<*>, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): DataFlowInfo { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractEffects)) return DataFlowInfo.EMPTY ++ ++ // Prevent launch of effect system machinery on pointless cases (constants/enums/constructors/etc.) ++ val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return DataFlowInfo.EMPTY ++ if (callExpression is KtDeclaration) return DataFlowInfo.EMPTY ++ ++ val resultContextInfo = getContextInfoWhen(ESReturns(UNKNOWN_CONSTANT), callExpression, bindingTrace, moduleDescriptor) ++ ++ return resultContextInfo.toDataFlowInfo(languageVersionSettings) ++ } ++ ++ fun recordDefiniteInvocations(resolvedCall: ResolvedCall<*>, bindingTrace: BindingTrace, moduleDescriptor: ModuleDescriptor) { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.CalledInPlaceEffect)) return ++ ++ // Prevent launch of effect system machinery on pointless cases (constants/enums/constructors/etc.) ++ val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return ++ if (callExpression is KtDeclaration) return ++ ++ val resultingContextInfo = getContextInfoWhen(ESReturns(UNKNOWN_CONSTANT), callExpression, bindingTrace, moduleDescriptor) ++ for (effect in resultingContextInfo.firedEffects) { ++ val callsEffect = effect as? ESCalls ?: continue ++ val id = callsEffect.callable.id as DataFlowValueID ++ ++ // Could be also IdentifierInfo.Variable when call passes non-anonymous lambda for callable parameter ++ val lambdaExpr = (id.dfv.identifierInfo as? DataFlowValueFactory.ExpressionIdentifierInfo)?.expression ?: continue ++ assert(lambdaExpr is KtLambdaExpression) { ""Unexpected argument of Calls-effect: expected KtLambdaExpression, got $lambdaExpr"" } ++ ++ bindingTrace.record(BindingContext.LAMBDA_INVOCATIONS, lambdaExpr as KtLambdaExpression, callsEffect.kind) ++ } ++ } ++ ++ fun getConditionalInfoForThenBranch( ++ condition: KtExpression?, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): DataFlowInfo { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractEffects)) return DataFlowInfo.EMPTY ++ if (condition == null) return DataFlowInfo.EMPTY ++ ++ return getContextInfoWhen(ESReturns(true.lift()), condition, bindingTrace, moduleDescriptor) ++ .toDataFlowInfo(languageVersionSettings) ++ } ++ ++ fun getConditionalInfoForElseBranch( ++ condition: KtExpression?, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): DataFlowInfo { ++ if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractEffects)) return DataFlowInfo.EMPTY ++ if (condition == null) return DataFlowInfo.EMPTY ++ ++ return getContextInfoWhen(ESReturns(false.lift()), condition, bindingTrace, moduleDescriptor) ++ .toDataFlowInfo(languageVersionSettings) ++ } ++ ++ private fun getContextInfoWhen( ++ observedEffect: ESEffect, ++ expression: KtExpression, ++ bindingTrace: BindingTrace, ++ moduleDescriptor: ModuleDescriptor ++ ): MutableContextInfo { ++ val schema = getSchema(expression, bindingTrace, moduleDescriptor) ?: return MutableContextInfo.EMPTY ++ ++ val extractedContextInfo = InfoCollector(observedEffect).collectFromSchema(schema) ++ ++ return extractedContextInfo ++ } ++ ++ private fun getSchema(expression: KtExpression, bindingTrace: BindingTrace, moduleDescriptor: ModuleDescriptor): EffectSchema? { ++ if (bindingTrace[BindingContext.EXPRESSION_EFFECTS, expression] == null) { ++ val evaluatedSchema = evaluateSchema(expression, bindingTrace.bindingContext, moduleDescriptor) ?: return null ++ bindingTrace.record(BindingContext.EXPRESSION_EFFECTS, expression, evaluatedSchema) ++ } ++ ++ return bindingTrace[BindingContext.EXPRESSION_EFFECTS, expression] ++ } ++ ++ private fun evaluateSchema(expression: KtExpression, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor): EffectSchema? { ++ val ctBuilder = CallTreeBuilder(bindingContext, moduleDescriptor, functorResolver) ++ val callTree = expression.accept(ctBuilder, Unit) ++ ++ val esBuilder = SchemaBuilder() ++ val schema = callTree.accept(esBuilder) ?: return null ++ ++ val reducedSchema = Reducer().reduceSchema(schema) ++ ++ return reducedSchema ++ } ++ ++ private fun checkAndRecordDefiniteInvocations(bindingTrace: BindingTrace, contextInfo: MutableContextInfo) {",BTW this guy is not in use now,2017-08-15 16:48:43 +972,"@@ -0,0 +1,16 @@ ++fun testIsNullOrBlank(x: String?) {","This test has no annotation of some language feature on. Looks strange. I'd check all new tests, and most probably all of them should have some annotation. Otherwise backward compatibility can be broken",2017-08-15 16:06:51 +737,"@@ -0,0 +1,160 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.descriptors.Visibility ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++ ++abstract class ClassifierType(tree: T,",May be it should be `sealed`,2017-04-05 15:54:03 +735,"@@ -0,0 +1,160 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.descriptors.Visibility ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++ ++abstract class ClassifierType(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCType(tree, treePath, javac), JavaClassifierType { ++ override val classifier by lazy { getClassifier(treePath, javac) } ++ ++ override val canonicalText ++ get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString() ++ ++ override val presentableText ++ get() = canonicalText ++ ++ private val typeParameter by lazy { ++ treePath.filter { it is JCTree.JCClassDecl || it is JCTree.JCMethodDecl } ++ .flatMap { ++ when (it) { ++ is JCTree.JCClassDecl -> it.typarams ++ is JCTree.JCMethodDecl -> it.typarams ++ else -> emptyList>()",May be throw an exception here? We should not achieve this point,2017-04-05 15:51:26 +738,"@@ -0,0 +1,160 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.descriptors.Visibility ++import org.jetbrains.kotlin.load.java.structure.* ++import org.jetbrains.kotlin.name.FqName ++ ++abstract class ClassifierType(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCType(tree, treePath, javac), JavaClassifierType { ++ override val classifier by lazy { getClassifier(treePath, javac) } ++ ++ override val canonicalText ++ get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString() ++ ++ override val presentableText ++ get() = canonicalText ++ ++ private val typeParameter by lazy { ++ treePath.filter { it is JCTree.JCClassDecl || it is JCTree.JCMethodDecl } ++ .flatMap { ++ when (it) { ++ is JCTree.JCClassDecl -> it.typarams ++ is JCTree.JCMethodDecl -> it.typarams ++ else -> emptyList>() ++ } ++ } ++ .find { it.toString().substringBefore("" "") == treePath.leaf.toString() } ++ } ++ ++} ++ ++class JCClassifierType(tree: T, ++ treePath: TreePath, ++ javac: Javac) : ClassifierType(tree, treePath, javac) { ++ ++ override val typeArguments: List ++ get() = emptyList() ++ ++ override val isRaw: Boolean ++ get() = (classifier as? JavaClass)?.typeParameters?.isNotEmpty() ?: false ++ ++} ++ ++class JCClassifierTypeWithTypeArgument(tree: T, ++ treePath: TreePath, ++ javac: Javac) : ClassifierType(tree, treePath, javac) { ++ ++ override val typeArguments: List ++ get() = tree.arguments.map { create(it, treePath, javac) } ++ ++ override val isRaw: Boolean ++ get() = false ++ ++} ++ ++private fun getClassifier(treePath: TreePath, javac: Javac) = treePath.resolve(javac).let { ++ it.second ++ ?: stubs[it.first] ++ ?: typeParameter(treePath, javac) ++ ?: createStubClassifier(it.first) ++} ++ ++private fun typeParameter(treePath: TreePath, javac: Javac) = treePath ++ .filter { it is JCTree.JCClassDecl || it is JCTree.JCMethodDecl } ++ .flatMap { ++ when (it) { ++ is JCTree.JCClassDecl -> it.typarams ++ is JCTree.JCMethodDecl -> it.typarams ++ else -> emptyList() ++ } ++ } ++ .find { it.toString().substringBefore("" "") == treePath.leaf.toString() } ++ ?.let { JCTypeParameter(it, ++ javac.getTreePath(it, treePath.compilationUnit), ++ javac) ++ } ++ ++private val stubs = hashMapOf()","Is it true we have some stub cache here? If yes, consider creating some class / object and integrate both `stubs` and `createStubClassifier` inside. I do not like mutable global properties, even private.",2017-04-05 15:57:50 +375,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and targeting ++ ++See [related discussion about Scala](http://lampwww.epfl.ch/~mihaylov/attributes.html). ++ ++## Discussion ++ ++For each option of annotations there's a general dichotomy of how it can be specified in code. ++ ++Option 0: Separate annotations ++ ++``` kotlin ++retention(SOURCE) ++target(CLASSIFIER, FIELD) ++annotation class example ++``` ++ ++Option 1: Make `annotation` into an annotation, and use its properties ++ ++``` kotlin ++annotation( ++ retention = SOURCE, ++ targets = array(CLASSIFIER, FIELD) ++) ++class example ++``` ++ ++A variation of this is ++ ++``` kotlin ++annotation(target(CLASSIFIER, FIELD), retention = SOURCE) class example ++``` ++ ++Annotations can be parameters to other annotations. ++ ++Having option as separate annotation is what Java has and seems more extensible, although it actually isn't (adding new parameters to one annotation is no better or worse than adding new annotation recognized by the compiler). ++ ++Having those as parameters is more discoverable, but has some syntactic shortcomings: no varargs can be used. ++ ++## Targeting ++ ++To check applicability, we can use the following constants: ++ ++| Kotlin constant | Java constant | ++|-----------------|---------------| ++| PACKAGE | \ | ++| CLASSIFIER | TYPE | ++| ANNOTATION_CLASS | ANNOTATION_TYPE | ++| TYPE_PARAMETER | \ ++| PROPERTY | \ | ++| FIELD | \ ++| LOCAL_VARIABLE | \ | ++| VALUE_PARAMETER | PARAMETER | ++| CONSTRUCTOR | \ | ++| FUNCITON | METHOD | ++| PROPERTY_GETTER | METHOD | ++| PROPERTY_SETTER | METHOD | ++| TYPE | TYPE_USE |","Is it ok that it called the same as other Java constant? Can it mislead? +",2015-04-10 12:14:58 +374,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and targeting ++ ++See [related discussion about Scala](http://lampwww.epfl.ch/~mihaylov/attributes.html). ++ ++## Discussion ++ ++For each option of annotations there's a general dichotomy of how it can be specified in code. ++ ++Option 0: Separate annotations ++ ++``` kotlin ++retention(SOURCE) ++target(CLASSIFIER, FIELD) ++annotation class example ++``` ++ ++Option 1: Make `annotation` into an annotation, and use its properties ++ ++``` kotlin ++annotation( ++ retention = SOURCE, ++ targets = array(CLASSIFIER, FIELD) ++) ++class example ++``` ++ ++A variation of this is ++ ++``` kotlin ++annotation(target(CLASSIFIER, FIELD), retention = SOURCE) class example ++``` ++ ++Annotations can be parameters to other annotations. ++ ++Having option as separate annotation is what Java has and seems more extensible, although it actually isn't (adding new parameters to one annotation is no better or worse than adding new annotation recognized by the compiler). ++ ++Having those as parameters is more discoverable, but has some syntactic shortcomings: no varargs can be used. ++ ++## Targeting ++ ++To check applicability, we can use the following constants: ++ ++| Kotlin constant | Java constant | ++|-----------------|---------------| ++| PACKAGE | \ | ++| CLASSIFIER | TYPE | ++| ANNOTATION_CLASS | ANNOTATION_TYPE | ++| TYPE_PARAMETER | \ ++| PROPERTY | \ | ++| FIELD | \ ++| LOCAL_VARIABLE | \ | ++| VALUE_PARAMETER | PARAMETER | ++| CONSTRUCTOR | \ | ++| FUNCITON | METHOD | ++| PROPERTY_GETTER | METHOD | ++| PROPERTY_SETTER | METHOD | ++| TYPE | TYPE_USE | ++| EXPRESSION | \ | ++","What about a file as target? +",2015-04-09 10:49:39 +361,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and trageting","Typo: trageting -> targeting +",2015-04-04 22:08:29 +362,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and trageting ++ ++See [related discussion about Scala](http://lampwww.epfl.ch/~mihaylov/attributes.html). ++ ++## Discussion ++ ++For each option of annotations there's a general dichotomy of how it can be specified in code. ++ ++Option 0: Separate annotations ++ ++``` kotlin ++retention(SOURCE) ++target(CLASSIFIER, FIELD) ++annotation class example ++``` ++ ++Option 1: Make `annotation` into an annotation, and use its properties ++ ++``` kotlin ++annotation( ++ retention = SOURCE, ++ targets = array(CLASSIFIER, FIELD) ++) ++class example ++``` ++ ++A variation of this is ++ ++``` kotlin ++annotation(target(CLASSIFIER, FIELD), retention = SOURCE) class example ++``` ++ ++Annotations can be parameters to other annotations. ++ ++Having option as separate annotation is what Java has and seems more extensible, although it actually isn't (adding new parameters to one annotation is no better or worse than adding new annotation recognized by the compiler). ++ ++Having those as parameters is more discoverable, but has some syntactic shortcomings: no varargs can be used. ++ ++## Targeting ++ ++To check applicability, we can use the following constants: ++ ++| Kotlin constant | Java constant | ++|-----------------|---------------| ++| PACKAGE | \ | ++| CLASSIFIER | TYPE | ++| ANNOTATION_CLASS | ANNOTATION_TYPE | ++| TYPE_PARAMETER | \ ++| PROPERTY | \ | ++| FIELD | \ ++| LOCAL_VARIABLE | \ | ++| VALUE_PARAMETER | PARAMETER | ++| CONSTRUCTOR | \ | ++| FUNCITON | METHOD | ++| PROPERTY_GETTER | METHOD | ++| PROPERTY_SETTER | METHOD | ++| TYPE | TYPE_USE | ++| EXPRESSION | \ | ++ ++Putting an annotation on an element that is not allowed by the specified target is a compile-time error. ++No targets specified means that all targets are accepted. ++ ++> NOTE: Java has the following [targets](https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html): ++ ++ ++**TODO** Open question: what about traits/classes/objects? ++**TODO** local variables are just like properties, but local ++ ++> Possbile platform-specific targets","Typo: Possbile -> Possible +",2015-04-04 22:24:09 +363,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and trageting ++ ++See [related discussion about Scala](http://lampwww.epfl.ch/~mihaylov/attributes.html). ++ ++## Discussion ++ ++For each option of annotations there's a general dichotomy of how it can be specified in code. ++ ++Option 0: Separate annotations ++ ++``` kotlin ++retention(SOURCE) ++target(CLASSIFIER, FIELD) ++annotation class example ++``` ++ ++Option 1: Make `annotation` into an annotation, and use its properties ++ ++``` kotlin ++annotation( ++ retention = SOURCE, ++ targets = array(CLASSIFIER, FIELD) ++) ++class example ++``` ++ ++A variation of this is ++ ++``` kotlin ++annotation(target(CLASSIFIER, FIELD), retention = SOURCE) class example ++``` ++ ++Annotations can be parameters to other annotations. ++ ++Having option as separate annotation is what Java has and seems more extensible, although it actually isn't (adding new parameters to one annotation is no better or worse than adding new annotation recognized by the compiler). ++ ++Having those as parameters is more discoverable, but has some syntactic shortcomings: no varargs can be used. ++ ++## Targeting ++ ++To check applicability, we can use the following constants: ++ ++| Kotlin constant | Java constant | ++|-----------------|---------------| ++| PACKAGE | \ | ++| CLASSIFIER | TYPE | ++| ANNOTATION_CLASS | ANNOTATION_TYPE | ++| TYPE_PARAMETER | \ ++| PROPERTY | \ | ++| FIELD | \ ++| LOCAL_VARIABLE | \ | ++| VALUE_PARAMETER | PARAMETER | ++| CONSTRUCTOR | \ | ++| FUNCITON | METHOD | ++| PROPERTY_GETTER | METHOD | ++| PROPERTY_SETTER | METHOD | ++| TYPE | TYPE_USE | ++| EXPRESSION | \ | ++ ++Putting an annotation on an element that is not allowed by the specified target is a compile-time error. ++No targets specified means that all targets are accepted. ++ ++> NOTE: Java has the following [targets](https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html): ++ ++ ++**TODO** Open question: what about traits/classes/objects? ++**TODO** local variables are just like properties, but local ++ ++> Possbile platform-specific targets ++* SINGLETON_FIELD for objects ++* PROPERTY_FIELD ++* (?) DEFAULT_FUNCTION ++* (?) LAMBDA_METHOD ++* PACKAGE_FACADE ++* PACKAGE_PART ++ ++### Mapping onto Java ++ ++Kotlin has more possible targets than Java, so there's an issue of mapping back and forth. The table above give a correspondence.","give -> gives +",2015-04-04 22:25:20 +364,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and trageting ++ ++See [related discussion about Scala](http://lampwww.epfl.ch/~mihaylov/attributes.html). ++ ++## Discussion ++ ++For each option of annotations there's a general dichotomy of how it can be specified in code. ++ ++Option 0: Separate annotations ++ ++``` kotlin ++retention(SOURCE) ++target(CLASSIFIER, FIELD) ++annotation class example ++``` ++ ++Option 1: Make `annotation` into an annotation, and use its properties ++ ++``` kotlin ++annotation( ++ retention = SOURCE, ++ targets = array(CLASSIFIER, FIELD) ++) ++class example ++``` ++ ++A variation of this is ++ ++``` kotlin ++annotation(target(CLASSIFIER, FIELD), retention = SOURCE) class example ++``` ++ ++Annotations can be parameters to other annotations. ++ ++Having option as separate annotation is what Java has and seems more extensible, although it actually isn't (adding new parameters to one annotation is no better or worse than adding new annotation recognized by the compiler). ++ ++Having those as parameters is more discoverable, but has some syntactic shortcomings: no varargs can be used. ++ ++## Targeting ++ ++To check applicability, we can use the following constants: ++ ++| Kotlin constant | Java constant | ++|-----------------|---------------| ++| PACKAGE | \ | ++| CLASSIFIER | TYPE | ++| ANNOTATION_CLASS | ANNOTATION_TYPE | ++| TYPE_PARAMETER | \ ++| PROPERTY | \ | ++| FIELD | \ ++| LOCAL_VARIABLE | \ | ++| VALUE_PARAMETER | PARAMETER | ++| CONSTRUCTOR | \ | ++| FUNCITON | METHOD | ++| PROPERTY_GETTER | METHOD | ++| PROPERTY_SETTER | METHOD | ++| TYPE | TYPE_USE | ++| EXPRESSION | \ | ++ ++Putting an annotation on an element that is not allowed by the specified target is a compile-time error. ++No targets specified means that all targets are accepted. ++ ++> NOTE: Java has the following [targets](https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html): ++ ++ ++**TODO** Open question: what about traits/classes/objects? ++**TODO** local variables are just like properties, but local ++ ++> Possbile platform-specific targets ++* SINGLETON_FIELD for objects ++* PROPERTY_FIELD ++* (?) DEFAULT_FUNCTION ++* (?) LAMBDA_METHOD ++* PACKAGE_FACADE ++* PACKAGE_PART ++ ++### Mapping onto Java ++ ++Kotlin has more possible targets than Java, so there's an issue of mapping back and forth. The table above give a correspondence. ++ ++When we compile a Kotlin class to Java, we write a `@java.lang.annotation.Target` annotation that reflects the targets. For targets having no correspondent ones in Java (e.g. `EXPRESSION`) nothing is written to `j.l.a.Target`. If the set of Java targets is empy, `j.l.a.Target` is not written to the class file. ++ ++In addition to `java.lang.annotation.Target`, a Kotlin-specific annotation `kotlin.target` is written containing all the Kotlin targets listed: ++ ++``` kotlin ++package kotlin ++ ++enum class AnnotationTarget { ++ PACKAGE ++ ... ++} ++ ++target(ANNOTATION_CLASS) ++annotation(RUNTIME) class target(vararg targets: AnnotationTarget) ++``` ++ ++When loading an annotation, we only read `kotlin.target`. When `kotlin.target` is missing, on the JVM, we read `j.l.a.Target` and map its values to Kotlin ones according to the table above. This implies that we can load pure Java annotations that know nothing about Kotlin, and that an annotation written in Java can be targeted, e.g. for Kotlin expressions, because one can simply manually specify `kotlin.target` for it. ++ ++### Syntax ++ ++It makes sense to use `kotlin.target` explicitly in Kotlin code: ++ ++``` kotlin ++target(EXPRESSION, TYPE) ++annotation class MyAnn ++``` ++ ++> An alternative would be to make target a aproperty of `kotlin.annotation`, but then we'd","aproperty -> property +",2015-04-04 22:29:18 +365,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and trageting ++ ++See [related discussion about Scala](http://lampwww.epfl.ch/~mihaylov/attributes.html). ++ ++## Discussion ++ ++For each option of annotations there's a general dichotomy of how it can be specified in code. ++ ++Option 0: Separate annotations ++ ++``` kotlin ++retention(SOURCE) ++target(CLASSIFIER, FIELD) ++annotation class example ++``` ++ ++Option 1: Make `annotation` into an annotation, and use its properties ++ ++``` kotlin ++annotation( ++ retention = SOURCE, ++ targets = array(CLASSIFIER, FIELD) ++) ++class example ++``` ++ ++A variation of this is ++ ++``` kotlin ++annotation(target(CLASSIFIER, FIELD), retention = SOURCE) class example ++``` ++ ++Annotations can be parameters to other annotations. ++ ++Having option as separate annotation is what Java has and seems more extensible, although it actually isn't (adding new parameters to one annotation is no better or worse than adding new annotation recognized by the compiler). ++ ++Having those as parameters is more discoverable, but has some syntactic shortcomings: no varargs can be used. ++ ++## Targeting ++ ++To check applicability, we can use the following constants: ++ ++| Kotlin constant | Java constant | ++|-----------------|---------------| ++| PACKAGE | \ | ++| CLASSIFIER | TYPE | ++| ANNOTATION_CLASS | ANNOTATION_TYPE | ++| TYPE_PARAMETER | \ ++| PROPERTY | \ | ++| FIELD | \ ++| LOCAL_VARIABLE | \ | ++| VALUE_PARAMETER | PARAMETER | ++| CONSTRUCTOR | \ | ++| FUNCITON | METHOD | ++| PROPERTY_GETTER | METHOD | ++| PROPERTY_SETTER | METHOD | ++| TYPE | TYPE_USE | ++| EXPRESSION | \ | ++ ++Putting an annotation on an element that is not allowed by the specified target is a compile-time error. ++No targets specified means that all targets are accepted. ++ ++> NOTE: Java has the following [targets](https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html): ++ ++ ++**TODO** Open question: what about traits/classes/objects? ++**TODO** local variables are just like properties, but local ++ ++> Possbile platform-specific targets ++* SINGLETON_FIELD for objects ++* PROPERTY_FIELD ++* (?) DEFAULT_FUNCTION ++* (?) LAMBDA_METHOD ++* PACKAGE_FACADE ++* PACKAGE_PART ++ ++### Mapping onto Java ++ ++Kotlin has more possible targets than Java, so there's an issue of mapping back and forth. The table above give a correspondence. ++ ++When we compile a Kotlin class to Java, we write a `@java.lang.annotation.Target` annotation that reflects the targets. For targets having no correspondent ones in Java (e.g. `EXPRESSION`) nothing is written to `j.l.a.Target`. If the set of Java targets is empy, `j.l.a.Target` is not written to the class file. ++ ++In addition to `java.lang.annotation.Target`, a Kotlin-specific annotation `kotlin.target` is written containing all the Kotlin targets listed: ++ ++``` kotlin ++package kotlin ++ ++enum class AnnotationTarget { ++ PACKAGE ++ ... ++} ++ ++target(ANNOTATION_CLASS) ++annotation(RUNTIME) class target(vararg targets: AnnotationTarget) ++``` ++ ++When loading an annotation, we only read `kotlin.target`. When `kotlin.target` is missing, on the JVM, we read `j.l.a.Target` and map its values to Kotlin ones according to the table above. This implies that we can load pure Java annotations that know nothing about Kotlin, and that an annotation written in Java can be targeted, e.g. for Kotlin expressions, because one can simply manually specify `kotlin.target` for it. ++ ++### Syntax ++ ++It makes sense to use `kotlin.target` explicitly in Kotlin code: ++ ++``` kotlin ++target(EXPRESSION, TYPE) ++annotation class MyAnn ++``` ++ ++> An alternative would be to make target a aproperty of `kotlin.annotation`, but then we'd ++* lose the advantage of varargs, because there are more optional parameters ++* be non-uniform with Java, thus making it harder to figure how to make a Java annotation Kotlin-friendly ++ ++## Retention ++ ++> NOTE: Retention is a Java-specific concern, more or less. CLR retains all attributes at runtime, and JS too ++ ++It makes a lot of sense to make `RUNTIME` the default retention. ++ ++Since `RetentionPolicy.CLASS` is not a good fit for Kotlin that has functions outside any class, it's better to have `BINARY` instead. Also, we could have use `java.lang.annotation.RetentionPolicy` anyways, since it's platform-specific. Thus, we need to have our own enum: ++","could have use -> could not use (?) +",2015-04-04 22:31:40 +359,"@@ -0,0 +1,169 @@ ++# Annotation Options ++ ++Goals: ++* Support annotation options, such as retention policy and trageting ++ ++See [related discussion about Scala](http://lampwww.epfl.ch/~mihaylov/attributes.html). ++ ++## Discussion ++ ++For each option of annotations there's a general dichotomy of how it can be specified in code. ++ ++Option 0: Separate annotations ++ ++``` kotlin ++retention(SOURCE) ++target(CLASSIFIER, FIELD) ++annotation class example ++``` ++ ++Option 1: Make `annotation` into an annotation, and use its properties ++ ++``` kotlin ++annotation( ++ retention = SOURCE, ++ targets = array(CLASSIFIER, FIELD) ++) ++class example ++``` ++ ++A variation of this is ++ ++``` kotlin ++annotation(target(CLASSIFIER, FIELD), retention = SOURCE) class example ++``` ++ ++Annotations can be parameters to other annotations. ++ ++Having option as separate annotation is what Java has and seems more extensible, although it actually isn't (adding new parameters to one annotation is no better or worse than adding new annotation recognized by the compiler). ++ ++Having those as parameters is more discoverable, but has some syntactic shortcomings: no varargs can be used. ++ ++## Targeting ++ ++To check applicability, we can use the following constants: ++ ++| Kotlin constant | Java constant | ++|-----------------|---------------| ++| PACKAGE | \ | ++| CLASSIFIER | TYPE | ++| ANNOTATION_CLASS | ANNOTATION_TYPE | ++| TYPE_PARAMETER | \ ++| PROPERTY | \ | ++| FIELD | \ ++| LOCAL_VARIABLE | \ | ++| VALUE_PARAMETER | PARAMETER | ++| CONSTRUCTOR | \ | ++| FUNCITON | METHOD | ++| PROPERTY_GETTER | METHOD | ++| PROPERTY_SETTER | METHOD | ++| TYPE | TYPE_USE | ++| EXPRESSION | \ | ++ ++Putting an annotation on an element that is not allowed by the specified target is a compile-time error. ++No targets specified means that all targets are accepted. ++ ++> NOTE: Java has the following [targets](https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html): ++ ++ ++**TODO** Open question: what about traits/classes/objects? ++**TODO** local variables are just like properties, but local ++ ++> Possbile platform-specific targets ++* SINGLETON_FIELD for objects ++* PROPERTY_FIELD ++* (?) DEFAULT_FUNCTION ++* (?) LAMBDA_METHOD ++* PACKAGE_FACADE ++* PACKAGE_PART ++ ++### Mapping onto Java ++ ++Kotlin has more possible targets than Java, so there's an issue of mapping back and forth. The table above give a correspondence. ++ ++When we compile a Kotlin class to Java, we write a `@java.lang.annotation.Target` annotation that reflects the targets. For targets having no correspondent ones in Java (e.g. `EXPRESSION`) nothing is written to `j.l.a.Target`. If the set of Java targets is empy, `j.l.a.Target` is not written to the class file. ++ ++In addition to `java.lang.annotation.Target`, a Kotlin-specific annotation `kotlin.target` is written containing all the Kotlin targets listed: ++ ++``` kotlin ++package kotlin ++ ++enum class AnnotationTarget { ++ PACKAGE ++ ... ++} ++ ++target(ANNOTATION_CLASS) ++annotation(RUNTIME) class target(vararg targets: AnnotationTarget) ++``` ++ ++When loading an annotation, we only read `kotlin.target`. When `kotlin.target` is missing, on the JVM, we read `j.l.a.Target` and map its values to Kotlin ones according to the table above. This implies that we can load pure Java annotations that know nothing about Kotlin, and that an annotation written in Java can be targeted, e.g. for Kotlin expressions, because one can simply manually specify `kotlin.target` for it. ++ ++### Syntax ++ ++It makes sense to use `kotlin.target` explicitly in Kotlin code: ++ ++``` kotlin ++target(EXPRESSION, TYPE) ++annotation class MyAnn ++``` ++ ++> An alternative would be to make target a aproperty of `kotlin.annotation`, but then we'd ++* lose the advantage of varargs, because there are more optional parameters ++* be non-uniform with Java, thus making it harder to figure how to make a Java annotation Kotlin-friendly ++ ++## Retention ++ ++> NOTE: Retention is a Java-specific concern, more or less. CLR retains all attributes at runtime, and JS too ++ ++It makes a lot of sense to make `RUNTIME` the default retention. ++ ++Since `RetentionPolicy.CLASS` is not a good fit for Kotlin that has functions outside any class, it's better to have `BINARY` instead. Also, we could have use `java.lang.annotation.RetentionPolicy` anyways, since it's platform-specific. Thus, we need to have our own enum: ++ ++``` kotlin ++package kotlin ++ ++enum class AnnotationRetention { ++ SOURCE ++ BINARY ++ RUNTIME ++} ++``` ++ ++> Now, we could map `java.lang.annotation.Retention` and `RetentionPolicy` to `kotlin.retention` and `kotlin.AnnotationRetention`, and then map `CLASS` to `BINARY`, but that is a little too much ++ ++Then, it makes sense to make `retention` a property of `kotlin.annotation`: ++ ++``` kotlin ++target(TYPE) ++annotation(SOURCE) class MyAnn ++``` ++ ++The following checks must be performed at compile time: ++* `EXPRESSION`-targeted annotations can only have retention `SOURCE` ++ ++## Repeatable ++ ++> Java has `Repeatable` as an annotation, but we cannot map a Kotlin type to it, because it is only present since JDK 8, and cannot be written to class files with version lower than 8. ++ ++We make `repeatable` a boolean property of `kotlin.annotation`, with default value `false` (as in Java and C#). ++ ++If a non-repeatable annotation is used multiple times on the same element, it is a compile-time error. ++ ++If a repeatable annotation is used multiple times on the same element, but the target byte code version is lower than Java 8, it is a compile-time error. ++ ++## Inherited and Documented ++ ++These two options have ratehr unclear value, and we do not supprt them in Kotlin. One can use platform-specific annotations to express them. ++ ++## Appendix. Definition of kotlin.annotation ++ ++``` kotlin ++package kotlin ++ ++target(CLASSIFIER)","Should it be `ANNOTATION_CLASS`? +",2015-04-03 15:25:27 +358,"@@ -0,0 +1,17 @@ ++// !DIAGNOSTICS: -UNUSED_PARAMETER ++class C { ++ [kotlin.jvm.overloads] private fun foo(s: String = ""OK"") { ++ } ++} ++ ++fun foo() { ++ class D { ++ [kotlin.jvm.overloads] fun foo(s: String = ""OK"") { ++ } ++ } ++ ++ val x = object { ++ [kotlin.jvm.overloads] fun foo(s: String = ""OK"") { ++ } ++ } ++}","Please also add an `internal` member with `overloads` here, to ensure the warning is not reported on it +",2015-04-01 14:28:30 +33,"@@ -0,0 +1,17 @@ ++package test ++open class Foo() { ++open fun execute() : Unit { ++} ++} ++open class Bar() { ++var fooNotNull : Foo = Foo() ++var fooNullable : Foo? = null ++} ++open class Test() { ++public open fun test(barNotNull : Bar, barNullable : Bar?) : Unit { ++barNotNull.fooNotNull.execute() ++barNotNull.fooNullable?.execute() ++barNullable?.fooNotNull?.execute() ++barNullable?.fooNullable?.execute() ++} ++} +\ No newline at end of file","Please fix code formatting in this test +",2013-02-21 14:56:11 +835,"@@ -0,0 +1,181 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.tree.Tree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaClassifier ++import org.jetbrains.kotlin.name.FqName ++ ++class TreePathResolverCache(private val javac: JavacWrapper) { ++ ++ private val cache = hashMapOf() ++ ++ fun resolve(treePath: TreePath): JavaClassifier? = with(treePath) { ++ if (cache.containsKey(leaf)) return cache[leaf] ++ ++ return tryToGetClassifier().apply { cache[leaf] = this } ++ } ++ ++ private fun TreePath.tryToGetClassifier(): JavaClassifier? { ++ val name = leaf.toString().substringBefore(""<"").substringAfter(""@"") ++ val nameParts = name.split(""."") ++ ++ with(compilationUnit as JCTree.JCCompilationUnit) { ++ tryToResolveInner(name, javac, nameParts)?.let { return it } ++ tryToResolvePackageClass(name, javac, nameParts)?.let { return it } ++ tryToResolveByFqName(name, javac)?.let { return it } ++ tryToResolveSingleTypeImport(name, javac, nameParts)?.let { return it } ++ tryToResolveTypeImportOnDemand(name, javac, nameParts)?.let { return it } ++ tryToResolveInJavaLang(name, javac)?.let { return it } ++ } ++ ++ return tryToResolveTypeParameter(javac) ++ } ++ ++ private fun TreePath.tryToResolveInner(name: String, ++ javac: JavacWrapper, ++ nameParts: List = emptyList()): JavaClass? = findEnclosingClasses(javac) ++ ?.forEach { ++ it.findInner(name, javac, nameParts)?.let { return it } ++ }.let { return null } ++ ++ private fun TreePath.findEnclosingClasses(javac: JavacWrapper) = filterIsInstance() ++ .filter { it.extending != leaf && !it.implementing.contains(leaf) } ++ .reversed() ++ .joinToString(separator = ""."", prefix = ""${compilationUnit.packageName}."") { it.simpleName } ++ .let { javac.findClass(FqName(it)) } ++ ?.let { ++ arrayListOf(it).apply { ++ var enclosingClass = it.outerClass ++ while (enclosingClass != null) { ++ add(enclosingClass) ++ enclosingClass = enclosingClass.outerClass ++ } ++ } ++ } ++ ++ private fun JCTree.JCCompilationUnit.tryToResolveSingleTypeImport(name: String, ++ javac: JavacWrapper, ++ nameParts: List = emptyList()): JavaClass? { ++ nameParts.size ++ .takeIf { it > 1 } ++ ?.let { ++ imports.filter { it.qualifiedIdentifier.toString().endsWith("".${nameParts.first()}"") } ++ .forEach { find(FqName(""${it.qualifiedIdentifier}""), javac, nameParts)?.let { return it } } ++ .let { return null } ++ } ++ ++ return imports ++ .find { it.qualifiedIdentifier.toString().endsWith("".$name"") } ++ ?.let { ++ FqName(it.qualifiedIdentifier.toString()) ++ .let { javac.findClass(it) ?: javac.getKotlinClassifier(it) } ++ } ++ } ++ ++ private fun JCTree.JCCompilationUnit.tryToResolvePackageClass(name: String, ++ javac: JavacWrapper, ++ nameParts: List = emptyList()): JavaClass? { ++ return nameParts.size ++ .takeIf { it > 1 } ++ ?.let { ++ find(FqName(""$packageName.${nameParts.first()}""), javac, nameParts) ++ } ?: javac.findClass(FqName(""$packageName.$name"")) ?: javac.getKotlinClassifier(FqName(""$packageName.$name"")) ++ } ++ ++ private fun JCTree.JCCompilationUnit.tryToResolveTypeImportOnDemand(name: String, ++ javac: JavacWrapper, ++ nameParts: List = emptyList()): JavaClass? { ++ with(imports.filter { it.qualifiedIdentifier.toString().endsWith(""*"") }) { ++ nameParts.size ++ .takeIf { it > 1 } ++ ?.let { ++ forEach { pack -> ++ find(FqName(""${pack.qualifiedIdentifier.toString().substringBefore(""*"")}${nameParts.first()}""), javac, nameParts) ++ ?.let { return it } ++ }.let { return null } ++ } ++ ++ forEach { ++ val fqName = ""${it.qualifiedIdentifier.toString().substringBefore(""*"")}$name"".let(::FqName) ++ (javac.findClass(fqName) ?: javac.getKotlinClassifier(fqName))?.let { return it } ++ }.let { return null } ++ } ++ } ++ ++ private fun TreePath.tryToResolveTypeParameter(javac: JavacWrapper) = ++ filter { it is JCTree.JCClassDecl || it is JCTree.JCMethodDecl }",This `filter` is not needed,2017-04-25 16:43:49 +410,"@@ -0,0 +1,183 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++ ++ ++fun> C.propToParams(p: P, conv: ((v: V) -> String) = { it.toString() } ) = ++ listOf(""--daemon-"" + p.name, conv(p.get(this))) ++ ++open class PropParser>(val dest: C, val prop: P, val parse: (s: String) -> V) { ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++fun Iterable.propParseFilter(parsers: List>) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ return filter { param -> ++ if (currentParser == null) { ++ currentParser = parsers.find { param.equals(""--daemon-"" + it.prop.name) } ++ if (currentParser != null) { ++ if (currentParser is BoolPropParser<*,*>) { ++ currentParser!!.apply("""") ++ currentParser = null ++ } ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++public interface CmdlineParams : Serializable { ++ public val asParams: Iterable ++ public val parsers: List> ++} ++ ++public fun Iterable.propParseFilter(vararg cs: CmdlineParams) : Iterable = ++ propParseFilter(cs.flatMap { it.parsers }) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var jvmParams: List = listOf() ++) : CmdlineParams { ++ ++ override val asParams: Iterable ++ get() = ++ propToParams(::jvmParams, { it.joinToString(""##"") }) // TODO: consider some other options rather than using potentially dangerous delimiter ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::jvmParams, { it.split(""##"")})) // TODO: see appropriate comment in asParams ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */, ++ public var autoshutdownIdleSeconds: Int = 0 /* 0 means unchecked */, ++ public var startEcho: String = COMPILER_SERVICE_RMI_NAME ++) : CmdlineParams { ++ ++ override val asParams: Iterable ++ get() = ++ propToParams(::port) + ++ propToParams(::autoshutdownMemoryThreshold) + ++ propToParams(::autoshutdownIdleSeconds) + ++ propToParams(::startEcho) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::port, { it.toInt()}), ++ PropParser(this, ::autoshutdownMemoryThreshold, { it.toLong()}), ++ PropParser(this, ::autoshutdownIdleSeconds, { it.toInt()}), ++ PropParser(this, ::startEcho, { it.trim('""') })) ++} ++ ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++ ++fun updateSingleFileDigest(file: File, md: MessageDigest) { ++ val stream = DigestInputStream(file.inputStream(), md) ++ val buf = ByteArray(1024) ++ while (stream.read(buf) == buf.size()) {}","It is not guaranteed that the `read` operation reads the same amount of bytes as buffer can contain and it even may read zero bytes even if the file pointer is not at the end +",2015-08-19 22:36:30 +411,"@@ -0,0 +1,183 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++ ++ ++fun> C.propToParams(p: P, conv: ((v: V) -> String) = { it.toString() } ) = ++ listOf(""--daemon-"" + p.name, conv(p.get(this))) ++ ++open class PropParser>(val dest: C, val prop: P, val parse: (s: String) -> V) { ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++fun Iterable.propParseFilter(parsers: List>) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ return filter { param -> ++ if (currentParser == null) { ++ currentParser = parsers.find { param.equals(""--daemon-"" + it.prop.name) } ++ if (currentParser != null) { ++ if (currentParser is BoolPropParser<*,*>) { ++ currentParser!!.apply("""") ++ currentParser = null ++ } ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++public interface CmdlineParams : Serializable { ++ public val asParams: Iterable ++ public val parsers: List> ++} ++ ++public fun Iterable.propParseFilter(vararg cs: CmdlineParams) : Iterable = ++ propParseFilter(cs.flatMap { it.parsers }) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var jvmParams: List = listOf() ++) : CmdlineParams { ++ ++ override val asParams: Iterable ++ get() = ++ propToParams(::jvmParams, { it.joinToString(""##"") }) // TODO: consider some other options rather than using potentially dangerous delimiter ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::jvmParams, { it.split(""##"")})) // TODO: see appropriate comment in asParams ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */, ++ public var autoshutdownIdleSeconds: Int = 0 /* 0 means unchecked */, ++ public var startEcho: String = COMPILER_SERVICE_RMI_NAME ++) : CmdlineParams { ++ ++ override val asParams: Iterable ++ get() = ++ propToParams(::port) + ++ propToParams(::autoshutdownMemoryThreshold) + ++ propToParams(::autoshutdownIdleSeconds) + ++ propToParams(::startEcho) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::port, { it.toInt()}), ++ PropParser(this, ::autoshutdownMemoryThreshold, { it.toLong()}), ++ PropParser(this, ::autoshutdownIdleSeconds, { it.toInt()}), ++ PropParser(this, ::startEcho, { it.trim('""') })) ++} ++ ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++ ++fun updateSingleFileDigest(file: File, md: MessageDigest) { ++ val stream = DigestInputStream(file.inputStream(), md) ++ val buf = ByteArray(1024) ++ while (stream.read(buf) == buf.size()) {} ++ stream.close()","shouldn't we use [`use` function](http://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html) here: + +``` +DigestInputStream(file.inputStream(), md).use { stream -> + // do stuff +} +``` +",2015-08-19 22:38:52 +144,"@@ -0,0 +1,185 @@ ++/* ++* Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lang.psi.JetPostfixExpression ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lexer.JetTokens ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetElement ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector ++ ++public class OperatorToFunctionIntention : JetSelfTargetingIntention(""operator.to.function"", javaClass()) { ++ fun isApplicablePrefix(element: JetPrefixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS, JetTokens.EXCL -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicablePostfix(element: JetPostfixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUSPLUS, JetTokens.MINUSMINUS -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicableBinary(element: JetBinaryExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.MUL, JetTokens.DIV, JetTokens.PERC, JetTokens.RANGE, JetTokens.IN_KEYWORD, JetTokens.NOT_IN, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.GT, JetTokens.LT, JetTokens.GTEQ, JetTokens.LTEQ -> true ++ JetTokens.EQ -> element.getLeft() is JetArrayAccessExpression ++ else -> false ++ } ++ } ++ ++ fun isApplicableArrayAccess(element: JetArrayAccessExpression): Boolean { ++ return true ++ } ++ ++ fun isApplicableCall(element: JetCallExpression): Boolean { ++ return element.getParent() !is JetDotQualifiedExpression && element.getValueArgumentList() != null ++ } ++ ++ override fun isApplicableTo(element: JetExpression): Boolean { ++ return when (element) { ++ is JetPrefixExpression -> isApplicablePrefix(element) ++ // is JetPostfixExpression -> isApplicablePostfix(element) ++ is JetBinaryExpression -> isApplicableBinary(element) ++ is JetArrayAccessExpression -> isApplicableArrayAccess(element) ++ is JetCallExpression -> isApplicableCall(element) ++ else -> false ++ } ++ } ++ ++ ++ fun convertPrefix(element: JetPrefixExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val base = element.getBaseExpression()!!.getText() ++ ++ val call = when (op) { ++ JetTokens.PLUS -> ""plus()"" ++ JetTokens.MINUS -> ""minus()"" ++ JetTokens.PLUSPLUS -> ""inc()"" ++ JetTokens.MINUSMINUS -> ""dec()"" ++ JetTokens.EXCL -> ""not()"" ++ else -> return ++ } ++ ++ val transformation = ""$base.$call"" ++ val transformed = JetPsiFactory.createExpression(element.getProject(), transformation) ++ element.replace(transformed) ++ } ++ ++ fun convertBinary(element: JetBinaryExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val left = element.getLeft()!! ++ val right = element.getRight()!! ++ val leftText = left.getText() ++ val rightText = right.getText() ++ ++ if (op == JetTokens.EQ) { ++ if (left is JetArrayAccessExpression) { ++ convertArrayAccess(left as JetArrayAccessExpression) ++ } ++ return ++ } ++ ++ val transformation = when (op) { ++ JetTokens.PLUS -> ""$leftText.plus($rightText)"" ++ JetTokens.MINUS -> ""$leftText.minus($rightText)"" ++ JetTokens.MUL -> ""$leftText.times($rightText)"" ++ JetTokens.DIV -> ""$leftText.div($rightText)"" ++ JetTokens.PERC -> ""$leftText.mod($rightText)"" ++ JetTokens.RANGE -> ""$leftText.rangeTo($rightText)"" ++ JetTokens.IN_KEYWORD -> ""$rightText.contains($leftText)"" ++ JetTokens.NOT_IN -> ""!$rightText.contains($leftText)"" ++ JetTokens.PLUSEQ -> ""$leftText.plusAssign($rightText)"" ++ JetTokens.MINUSEQ -> ""$leftText.minusAssign($rightText)"" ++ JetTokens.MULTEQ -> ""$leftText.timesAssign($rightText)"" ++ JetTokens.DIVEQ -> ""$leftText.divAssign($rightText)"" ++ JetTokens.PERCEQ -> ""$leftText.modAssign($rightText)"" ++ JetTokens.EQEQ -> ""$leftText?.equals($rightText) ?: $rightText.identityEquals(null)"" ++ JetTokens.EXCLEQ -> ""!($leftText?.equals($rightText) ?: $rightText.identityEquals(null))"" ++ JetTokens.GT -> ""$leftText.compareTo($rightText) > 0"" ++ JetTokens.LT -> ""$leftText.compareTo($rightText) < 0"" ++ JetTokens.GTEQ -> ""$leftText.compareTo($rightText) >= 0"" ++ JetTokens.LTEQ -> ""$leftText.compareTo($rightText) <= 0"" ++ else -> return ++ } ++ ++ val transformed = JetPsiFactory.createExpression(element.getProject(), transformation) ++ ++ val newCalleeExpression = left ++ val context = AnalyzerFacadeWithCache.getContextForElement(newCalleeExpression) ++ val functionCandidates = context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, newCalleeExpression]","`functionCandidates` is always null for me here. I think it has to do with me using a the `PsiElement` `left` rather than a `JetElement`. I can't seem to figure out what it is, though. Is there a way to create a `JetElement` from a string? +",2014-04-07 07:49:29 +422,"@@ -0,0 +1,192 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.service ++ ++import org.jetbrains.kotlin.cli.common.CLICompiler ++import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler ++import org.jetbrains.kotlin.config.Services ++import org.jetbrains.kotlin.incremental.components.LookupTracker ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.rmi.* ++import org.jetbrains.kotlin.rmi.service.RemoteIncrementalCacheClient ++import org.jetbrains.kotlin.rmi.service.RemoteOutputStreamClient ++import java.io.File ++import java.io.FileNotFoundException ++import java.io.IOException ++import java.io.PrintStream ++import java.net.URLClassLoader ++import java.rmi.registry.Registry ++import java.rmi.server.UnicastRemoteObject ++import java.util.* ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import java.util.jar.Manifest ++import java.util.logging.Logger ++import kotlin.concurrent.read ++import kotlin.concurrent.write ++ ++ ++class CompileServiceImpl>( ++ val registry: Registry, ++ val compiler: Compiler, ++ val selfCompilerId: CompilerId, ++ val daemonOptions: DaemonOptions ++) : CompileService, UnicastRemoteObject() { ++ ++ val log by lazy { Logger.getLogger(""compiler"") } ++ ++ private val rwlock = ReentrantReadWriteLock() ++ private var alive = false ++ ++ // TODO: consider matching compilerId coming from outside with actual one ++// private val selfCompilerId by lazy { ++// CompilerId( ++// compilerClasspath = System.getProperty(""java.class.path"") ++// ?.split(File.pathSeparator) ++// ?.map { File(it) } ++// ?.filter { it.exists() } ++// ?.map { it.absolutePath } ++// ?: listOf(), ++// compilerVersion = loadKotlinVersionFromResource() ++// ) ++// } ++ ++ init { ++ // assuming logically synchronized ++ try { ++ // cleanup for the case of incorrect restart ++ UnicastRemoteObject.unexportObject(this, false) ++ } ++ catch (e: java.rmi.NoSuchObjectException) { ++ // ignoring if object already exported ++ } ++ ++ val stub = UnicastRemoteObject.exportObject(this, 0) as CompileService ++ // TODO: use version-specific name ++ registry.rebind (COMPILER_SERVICE_RMI_NAME, stub); ++ alive = true ++ } ++ ++ public class IncrementalCompilationComponentsImpl(val idToCache: Map): IncrementalCompilationComponents { ++ // perf: cheap object, but still the pattern may be costly if there are too many calls to cache with the same id (which seems not to be the case now) ++ override fun getIncrementalCache(moduleId: String): IncrementalCache = RemoteIncrementalCacheClient(idToCache[moduleId]!!) ++ override fun getLookupTracker(): LookupTracker = LookupTracker.DO_NOTHING ++ } ++ ++ private fun createCompileServices(incrementalCaches: Map): Services = ++ Services.Builder() ++ .register(javaClass(), IncrementalCompilationComponentsImpl(incrementalCaches)) ++// .register(javaClass(), object: CompilationCanceledStatus { ++// override fun checkCanceled(): Unit = if (context.getCancelStatus().isCanceled()) throw CompilationCanceledException() ++// }) ++ .build() ++ ++ ++ fun usedMemory(): Long { ++ System.gc() ++ val rt = Runtime.getRuntime() ++ return (rt.totalMemory() - rt.freeMemory())","I think you can get more accurate information using the MemoryMXBean class. +",2015-08-20 14:41:14 +983,"@@ -0,0 +1,194 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.builtins.DefaultBuiltIns ++import org.jetbrains.kotlin.descriptors.ModuleDescriptor ++import org.jetbrains.kotlin.effectsystem.factories.createConstant ++import org.jetbrains.kotlin.effectsystem.functors.* ++import org.jetbrains.kotlin.effectsystem.resolving.FunctorResolver ++import org.jetbrains.kotlin.effectsystem.structure.ESFunctor ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.structure.UNIT_ID ++import org.jetbrains.kotlin.effectsystem.structure.calltree.* ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory ++import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.utils.addToStdlib.cast ++import org.jetbrains.kotlin.utils.ifEmpty ++ ++/** ++ * Visits Psi-tree and builds Call Tree ++ */ ++class CallTreeBuilder( ++ private val bindingContext: BindingContext, ++ private val moduleDescriptor: ModuleDescriptor, ++ private val functorResolver: FunctorResolver ++) : KtVisitor() { ++ ++ override fun visitKtElement(element: KtElement, data: Unit): CTNode = UNKNOWN_CALL ++ ++ override fun visitConstantExpression(expression: KtConstantExpression, data: Unit): CTNode { ++ val bindingContext = bindingContext ++ ++ val type: KotlinType = bindingContext.getType(expression) ?: return UNKNOWN_CALL ++ ++ val compileTimeConstant: CompileTimeConstant<*> ++ = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression) ?: return UNKNOWN_CALL ++ val value: Any? = compileTimeConstant.getValue(type) ++ return CTConstant(ValueIdsFactory.idForConstant(value), type, value) ++ } ++ ++ override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Unit): CTNode { ++ // TODO: make proper resolving ++ if (expression.text == ""Unit"") return CTConstant(UNIT_ID, DefaultBuiltIns.Instance.unitType, Unit) ++ return tryCreateVariable(expression) ++ } ++ ++ override fun visitParenthesizedExpression(expression: KtParenthesizedExpression, data: Unit): CTNode { ++ val deparenthesized = KtPsiUtil.safeDeparenthesize(expression) ++ return if (deparenthesized == expression) UNKNOWN_CALL else deparenthesized.accept(this, data) ++ } ++ ++ override fun visitUnaryExpression(expression: KtUnaryExpression, data: Unit): CTCall { ++ tryGetCachedCall(expression)?.let { return it } ++ ++ val argNode = expression.baseExpression?.accept(this, data) ?: return UNKNOWN_CALL ++ return when (expression.operationToken) { ++ KtTokens.EXCL -> CTCall(NotFunctor(), listOf(argNode)) ++ else -> return UNKNOWN_CALL ++ } ++ } ++ ++ override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Unit): CTCall { ++ tryGetCachedCall(expression)?.let { return it } ++ ++ val receiver = expression.receiverExpression.accept(this, data) ++ ++ val resolvedCall = expression.selectorExpression.getResolvedCall(bindingContext) ?: return UNKNOWN_CALL ++ val argNodes = resolvedCall.valueArgumentsByIndex?.map { ++ (it as? ExpressionValueArgument)?.valueArgument?.getArgumentExpression()?.accept(this, data) ?: return UNKNOWN_CALL ++ } ?: return UNKNOWN_CALL ++ ++ val functor = functorResolver.resolveFunctor(resolvedCall) ?: return UNKNOWN_CALL ++ return CTCall(functor, listOf(receiver) + argNodes) ++ } ++ ++ override fun visitThisExpression(expression: KtThisExpression, data: Unit?): CTNode { ++ val dfv = expression.createDataFlowValue() ?: return UNKNOWN_CALL // Could be possible for unavailable/incorrect this ++ return CTVariable(ValueIdsFactory.dfvBased(dfv), dfv.type) ++ } ++ ++ override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, data: Unit?): CTNode = tryCreateVariable(expression) ++ ++ override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): CTNode = expression.baseExpression?.accept(this, data) ?: UNKNOWN_CALL ++ ++ override fun visitBinaryExpression(expression: KtBinaryExpression, data: Unit): CTCall { ++ tryGetCachedCall(expression)?.let { return it } ++ ++ val leftNode = expression.left?.accept(this, data) ?: return UNKNOWN_CALL ++ val rightNode = expression.right?.accept(this, data) ?: return UNKNOWN_CALL ++ ++ val functor = when (expression.operationToken) { ++ KtTokens.EQEQ, KtTokens.EQEQEQ -> {",Not quite sure should reference comparison be here.,2017-08-15 16:50:22 +30,"@@ -0,0 +1,2 @@ ++// ""Change type argument list to <*>"" ""true"" ++fun isStringList(list : Any?) = list is (List<String>)","At first, I've added the parentheses because this way it's more readable to me. But as I was trying to implement the quickfix I realised that it would be possible to make mistake in this case: change ""(List)"" to ""List<*>"". That's why I left the parentheses in one test case. +",2013-02-21 09:21:48 +370,"@@ -0,0 +1,202 @@ ++# @-based Syntax For Annotations ++ ++Goals: ++* Spare `[...]` in expression position for future use ++* Support targeting for annotations (`field`, `getter` etc) ++* Preserve affected/clashing functionality (`@labels`) ++* Support `open` and other modifiers on local classes ++ ++## Examples ++ ++Annotation: ++``` kotlin ++@AnnotationName(args) ++class Foo ++``` ++ ++Targeted annotation: ++``` kotlin ++class C(@field:Foo val x: Int, @field,parameter:Bar val y: Int) ++``` ++ ++another option (like in Scala): ++``` kotlin ++class C(@(Foo@field) val x: Int, @(Bar@(field,parameter)) val y: Int) ++``` ++ ++yet another option (requires allowing annotation arrays at least in source-retained annotations): ++ ++``` kotlin ++class C(@field(@Foo) val x: Int, @field(@Bar) @parameter(@Bar) val y: Int) ++``` ++ ++Labels: ++``` kotlin ++loop@ // declaring a label ++for (x in foo) { ++ if (x > 0) continue@loop // using a label ++} ++``` ++ ++## Syntactic Disambiguation ++ ++How can we avoid confusion between `continue@loop` and ++ ++``` kotlin ++if (foo) continue ++@ann val x = 1 ++``` ++ ++or `return@label (x + 1) + 5` and `return @ann(x + 1) +5` ++ ++Rules: ++* no newline allowed between `continue`/`break`/`this`/`super`/`return` and `@label` ++* only one label allowed after these keywords, everything after the first label is an annotation ++* for `return` we prefer `return@label` to `return @ann expr`, so one should say `return (@ann expr)` ++ ++## Targeting ++ ++Possible targets are ++* `field` ++* `get` ++* `set` ++* `property` ++* `parameter` - for constructor parameters that are also properties ++ ++Reasonable defaults would probably be: ++* `field` if there's a backing field ++* `get` otherwise","Maybe it's worth to mention default target for constructor parameters? Will it be `parameter` for simple parameters and for fields? +",2015-04-05 22:23:49 +371,"@@ -0,0 +1,202 @@ ++# @-based Syntax For Annotations ++ ++Goals: ++* Spare `[...]` in expression position for future use ++* Support targeting for annotations (`field`, `getter` etc) ++* Preserve affected/clashing functionality (`@labels`) ++* Support `open` and other modifiers on local classes ++ ++## Examples ++ ++Annotation: ++``` kotlin ++@AnnotationName(args) ++class Foo ++``` ++ ++Targeted annotation: ++``` kotlin ++class C(@field:Foo val x: Int, @field,parameter:Bar val y: Int) ++``` ++ ++another option (like in Scala): ++``` kotlin ++class C(@(Foo@field) val x: Int, @(Bar@(field,parameter)) val y: Int) ++``` ++ ++yet another option (requires allowing annotation arrays at least in source-retained annotations): ++ ++``` kotlin ++class C(@field(@Foo) val x: Int, @field(@Bar) @parameter(@Bar) val y: Int) ++``` ++ ++Labels: ++``` kotlin ++loop@ // declaring a label ++for (x in foo) { ++ if (x > 0) continue@loop // using a label ++} ++``` ++ ++## Syntactic Disambiguation ++ ++How can we avoid confusion between `continue@loop` and ++ ++``` kotlin ++if (foo) continue ++@ann val x = 1 ++``` ++ ++or `return@label (x + 1) + 5` and `return @ann(x + 1) +5` ++ ++Rules: ++* no newline allowed between `continue`/`break`/`this`/`super`/`return` and `@label` ++* only one label allowed after these keywords, everything after the first label is an annotation ++* for `return` we prefer `return@label` to `return @ann expr`, so one should say `return (@ann expr)` ++ ++## Targeting ++ ++Possible targets are ++* `field` ++* `get` ++* `set` ++* `property` ++* `parameter` - for constructor parameters that are also properties ++ ++Reasonable defaults would probably be: ++* `field` if there's a backing field ++* `get` otherwise ++ ++Otherwise, determined by the settings of the annotation itself (applicable to fields only -> goes to a field)","Shall we really allow omitting the non-default target in code? It's a clear message with quick-fix for a code writter and possible source of misunderstanding for a reader that can't be resolved without navigating to annotation declaration. And annotation target settings modification can lead to unexpected tools failures without any compiler messages on rebuild. +",2015-04-05 22:36:55 +369,"@@ -0,0 +1,202 @@ ++# @-based Syntax For Annotations ++ ++Goals: ++* Spare `[...]` in expression position for future use ++* Support targeting for annotations (`field`, `getter` etc) ++* Preserve affected/clashing functionality (`@labels`) ++* Support `open` and other modifiers on local classes ++ ++## Examples ++ ++Annotation: ++``` kotlin ++@AnnotationName(args) ++class Foo ++``` ++ ++Targeted annotation: ++``` kotlin ++class C(@field:Foo val x: Int, @field,parameter:Bar val y: Int) ++``` ++ ++another option (like in Scala): ++``` kotlin ++class C(@(Foo@field) val x: Int, @(Bar@(field,parameter)) val y: Int) ++``` ++ ++yet another option (requires allowing annotation arrays at least in source-retained annotations): ++ ++``` kotlin ++class C(@field(@Foo) val x: Int, @field(@Bar) @parameter(@Bar) val y: Int) ++``` ++ ++Labels: ++``` kotlin ++loop@ // declaring a label ++for (x in foo) { ++ if (x > 0) continue@loop // using a label ++} ++``` ++ ++## Syntactic Disambiguation ++ ++How can we avoid confusion between `continue@loop` and ++ ++``` kotlin ++if (foo) continue ++@ann val x = 1 ++``` ++ ++or `return@label (x + 1) + 5` and `return @ann(x + 1) +5` ++ ++Rules: ++* no newline allowed between `continue`/`break`/`this`/`super`/`return` and `@label` ++* only one label allowed after these keywords, everything after the first label is an annotation ++* for `return` we prefer `return@label` to `return @ann expr`, so one should say `return (@ann expr)` ++ ++## Targeting ++ ++Possible targets are ++* `field` ++* `get` ++* `set` ++* `property` ++* `parameter` - for constructor parameters that are also properties ++ ++Reasonable defaults would probably be: ++* `field` if there's a backing field ++* `get` otherwise ++ ++Otherwise, determined by the settings of the annotation itself (applicable to fields only -> goes to a field) ++ ++### Possible Syntax for Targeting ++ ++Special syntax: ++ ++``` kotlin ++class C(@field:Ann(""arg"") var foo: Int) ++``` ++ ++This is a rather limited dedicated solution: it is unclear, for example, how you define a new target, also this syntax can not be used for anything else but targeting. ++ ++Scala-like syntax: ++ ++``` kotlin ++class C(@(Ann@field)(""arg"") var foo: Int) ++``` ++ ++Too many parentheses, but the mechanism is generic. ++ ++Annotation-array-based syntax: ++ ++``` kotlin ++class C(@field(@Ann1(""arg""), @Ann2) var foo: Int) ++``` ++ ++Downside: to put the same annotation on two targets, we'd need to duplicate it. ++ ++For this, we need to allow annotation attributes of type `Array`: ++ ++``` kotlin ++annotation class field(vararg val annotations: Annotation) ++``` ++**NOTE**: This is only relatively easilty achievable for source-retained annotations, for class- or runtime-retained it's a lot more involved and relies on an undocumented features of JVM.","eastlty -> easily +",2015-04-05 22:18:54 +459,"@@ -0,0 +1,202 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.service ++ ++import org.jetbrains.kotlin.cli.common.CLICompiler ++import org.jetbrains.kotlin.config.Services ++import org.jetbrains.kotlin.incremental.components.LookupTracker ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.rmi.* ++import org.jetbrains.kotlin.rmi.service.RemoteIncrementalCacheClient ++import org.jetbrains.kotlin.rmi.service.RemoteOutputStreamClient ++import java.io.IOException ++import java.io.PrintStream ++import java.lang.management.ManagementFactory ++import java.net.URLClassLoader ++import java.rmi.registry.Registry ++import java.rmi.server.UnicastRemoteObject ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import java.util.jar.Manifest ++import java.util.logging.Logger ++import kotlin.concurrent.read ++import kotlin.concurrent.write ++ ++ ++class CompileServiceImpl>( ++ val registry: Registry, ++ val compiler: Compiler, ++ val selfCompilerId: CompilerId, ++ val daemonOptions: DaemonOptions ++) : CompileService, UnicastRemoteObject() { ++ ++ val log by lazy { Logger.getLogger(""compiler"") } ++ ++ private val rwlock = ReentrantReadWriteLock() ++ private var alive = false ++ ++ // TODO: consider matching compilerId coming from outside with actual one ++// private val selfCompilerId by lazy { ++// CompilerId( ++// compilerClasspath = System.getProperty(""java.class.path"") ++// ?.split(File.pathSeparator) ++// ?.map { File(it) } ++// ?.filter { it.exists() } ++// ?.map { it.absolutePath } ++// ?: listOf(), ++// compilerVersion = loadKotlinVersionFromResource() ++// ) ++// } ++ ++ init { ++ // assuming logically synchronized ++ try { ++ // cleanup for the case of incorrect restart ++ UnicastRemoteObject.unexportObject(this, false) ++ } ++ catch (e: java.rmi.NoSuchObjectException) { ++ // ignoring if object already exported ++ } ++ ++ val stub = UnicastRemoteObject.exportObject(this, 0) as CompileService ++ // TODO: use version-specific name ++ registry.rebind (COMPILER_SERVICE_RMI_NAME, stub); ++ alive = true ++ } ++ ++ public class IncrementalCompilationComponentsImpl(val idToCache: Map): IncrementalCompilationComponents { ++ // perf: cheap object, but still the pattern may be costly if there are too many calls to cache with the same id (which seems not to be the case now) ++ override fun getIncrementalCache(moduleId: String): IncrementalCache = RemoteIncrementalCacheClient(idToCache[moduleId]!!) ++ // TODO: add appropriate proxy into interaction when lookup tracker is needed ++ override fun getLookupTracker(): LookupTracker = LookupTracker.DO_NOTHING ++ } ++ ++ private fun createCompileServices(incrementalCaches: Map): Services = ++ Services.Builder() ++ .register(IncrementalCompilationComponents::class.java, IncrementalCompilationComponentsImpl(incrementalCaches)) ++ // TODO: add remote proxy for cancellation status tracking ++// .register(javaClass(), object: CompilationCanceledStatus { ++// override fun checkCanceled(): Unit = if (context.getCancelStatus().isCanceled()) throw CompilationCanceledException() ++// }) ++ .build() ++ ++ ++ fun usedMemory(): Long { ++ System.gc() ++ val rt = Runtime.getRuntime() ++ return (rt.totalMemory() - rt.freeMemory()) ++ } ++ ++ fun usedMemoryMX(): Long { ++ System.gc() ++ val memoryMXBean= ManagementFactory.getMemoryMXBean() ++ val memHeap=memoryMXBean.getHeapMemoryUsage() ++ return memHeap.used ++ } ++ ++ // TODO: consider using version as a part of compiler ID or drop this function ++ private fun loadKotlinVersionFromResource(): String { ++ (javaClass.classLoader as? URLClassLoader) ++ ?.findResource(""META-INF/MANIFEST.MF"") ++ ?.let { ++ try { ++ return Manifest(it.openStream()).mainAttributes.getValue(""Implementation-Version"") ?: """" ++ } ++ catch (e: IOException) {} ++ } ++ return """" ++ } ++ ++ ++ fun checkedCompile(args: Array, body: () -> R): R { ++ try { ++ if (args.none()) ++ throw IllegalArgumentException(""Error: empty arguments list."") ++ log.info(""Starting compilation with args: "" + args.joinToString("" "")) ++ val startMemMX = usedMemoryMX() / 1024 ++ val startMem = usedMemory() / 1024 ++ val startTime = System.nanoTime() ++ val res = body() ++ val endTime = System.nanoTime() ++ val endMem = usedMemory() / 1024 ++ val endMemMX = usedMemoryMX() / 1024 ++ log.info(""Done with result "" + res.toString()) ++ log.info(""Elapsed time: "" + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + "" ms"") ++ log.info(""Used memory: $endMem kb (${""%+d"".format(endMem - startMem)} kb)"") ++ log.info(""Used memory (from MemoryMXBean): $endMemMX kb (${""%+d"".format(endMemMX - startMemMX)} kb)"") ++ return res ++ } ++ catch (e: Exception) { ++ log.info(""Error: $e"") ++ throw e ++ } ++ } ++ ++ fun ifAlive(body: () -> R): R = rwlock.read { ++ if (!alive) throw IllegalStateException(""Kotlin Compiler Service is not in alive state"") ++ else body() ++ } ++ ++ fun ifAliveExclusive(body: () -> R): R = rwlock.write { ++ if (!alive) throw IllegalStateException(""Kotlin Compiler Service is not in alive state"") ++ else body() ++ } ++ ++ // sometimes used for debugging ++ fun spy(msg: String, body: () -> R): R { ++ val res = body() ++ log.info(msg + "" = "" + res.toString()) ++ return res ++ } ++ ++ override fun getCompilerId(): CompilerId = ifAlive { selfCompilerId } ++ ++ override fun getUsedMemory(): Long = ifAlive { usedMemory() } ++ ++ override fun shutdown() { ++ ifAliveExclusive { ++ log.info(""Shutdown started"") ++ alive = false ++ UnicastRemoteObject.unexportObject(this, true) ++ log.info(""Shutdown complete"") ++ } ++ } ++ ++ override fun remoteCompile(args: Array, errStream: RemoteOutputStream, outputFormat: CompileService.OutputFormat): Int = ++ doCompile(args, errStream) { printStream -> ++ when (outputFormat) { ++ CompileService.OutputFormat.PLAIN -> compiler.exec(printStream, *args) ++ CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, Services.EMPTY, *args) ++ }.code ++ } ++ ++ override fun remoteIncrementalCompile(args: Array, caches: Map, outputStream: RemoteOutputStream, outputFormat: CompileService.OutputFormat): Int = ++ doCompile(args, outputStream) { printStream -> ++ when (outputFormat) { ++ CompileService.OutputFormat.PLAIN -> throw NotImplementedError(""Only XML output is supported in remote incremental compilation"") ++ CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, createCompileServices(caches), *args) ++ }.code ++ } ++ ++ fun doCompile(args: Array, errStream: RemoteOutputStream, body: (PrintStream) -> Int): Int =","I'd write something like: + +``` kotlin + override fun remoteCompile(args: Array, errStream: RemoteOutputStream, outputFormat: CompileService.OutputFormat): Int = + doCompile(args, errStream, outputFormat) { compiler.exec(it, *args) } + + override fun remoteIncrementalCompile(args: Array, caches: Map, outputStream: RemoteOutputStream, outputFormat: CompileService.OutputFormat): Int = + doCompile(args, outputStream, outputFormat) { throw NotImplementedError(""Only XML output is supported in remote incremental compilation"") } + + fun doCompile(args: Array, errStream: RemoteOutputStream, outputFormat: CompileService.OutputFormat, compileWithPlainOut: (PrintStream) -> ExitCode): Int = + ifAlive { + checkedCompile(args) { + val remoteStreamClient = RemoteOutputStreamClient(errStream) + val printStream = PrintStream(remoteStreamClient) + when (outputFormat) { + CompileService.OutputFormat.PLAIN -> compileWithPlainOut(printStream) + CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, Services.EMPTY, *args) + }.code + } + } +``` +",2015-08-31 11:34:37 +501,"@@ -0,0 +1,203 @@ ++/*","As far as I understand these functions are copies of functions at KotlinBuilder. Why not to reuse them at KotlinBuilder? I mean, these functions are in build common, so their originals from KotlinBuilder can be removed. +",2016-02-02 15:18:00 +350,"@@ -0,0 +1,204 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.codegen ++ ++import org.jetbrains.kotlin.codegen.binding.CodegenBinding ++import org.jetbrains.kotlin.codegen.context.CodegenContext ++import org.jetbrains.kotlin.codegen.state.GenerationState ++import org.jetbrains.kotlin.descriptors.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.JetClass ++import org.jetbrains.kotlin.psi.JetClassOrObject ++import org.jetbrains.kotlin.psi.JetElement ++import org.jetbrains.kotlin.psi.JetNamedFunction ++import org.jetbrains.kotlin.resolve.jvm.AsmTypes ++import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin ++import org.jetbrains.org.objectweb.asm.Opcodes ++import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter ++ ++/** ++ * Generates Java overloads for functions and constructors that have the default ++ * parameter values substituted. ++ */ ++public class DefaultParameterValueSubstitutor(val state: GenerationState) { ++ /** ++ * If all of the parameters of the specified constructor declare default values, ++ * generates a no-argument constructor that passes default values for all arguments. ++ */ ++ fun generateDefaultConstructorIfNeeded(constructorDescriptor: ConstructorDescriptor, ++ classBuilder: ClassBuilder, ++ context: CodegenContext<*>, ++ classOrObject: JetClassOrObject) { ++ if (!isEmptyConstructorNeeded(constructorDescriptor, classOrObject)) { ++ return ++ } ++ ++ generateOverloadWithSubstitutedParameters(constructorDescriptor, constructorDescriptor, classBuilder, classOrObject, ++ context, ++ constructorDescriptor.countDefaultParameters()) ++ } ++ ++ /** ++ * If the function is annotated with [kotlin.jvm.overloads], generates Java methods that ++ * have the default parameter values substituted. If a method has N parameters and M of which ++ * have default values, M overloads are generated: the first one takes N-1 parameters (all but ++ * the last one that takes a default value), the second takes N-2 parameters, and so on. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ */ ++ fun generateOverloadsIfNeeded(function: JetNamedFunction, ++ functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ owner: CodegenContext<*>, ++ classBuilder: ClassBuilder) { ++ val overloadsFqName = FqName.fromSegments(listOf(""kotlin"", ""jvm"", ""overloads""))","`FqName(""kotlin.jvm.overloads"")` would be more grep-friendly. Also I would make it a constant (either top-level or in the companion) +",2015-03-31 09:00:41 +351,"@@ -0,0 +1,204 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.codegen ++ ++import org.jetbrains.kotlin.codegen.binding.CodegenBinding ++import org.jetbrains.kotlin.codegen.context.CodegenContext ++import org.jetbrains.kotlin.codegen.state.GenerationState ++import org.jetbrains.kotlin.descriptors.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.JetClass ++import org.jetbrains.kotlin.psi.JetClassOrObject ++import org.jetbrains.kotlin.psi.JetElement ++import org.jetbrains.kotlin.psi.JetNamedFunction ++import org.jetbrains.kotlin.resolve.jvm.AsmTypes ++import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin ++import org.jetbrains.org.objectweb.asm.Opcodes ++import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter ++ ++/** ++ * Generates Java overloads for functions and constructors that have the default ++ * parameter values substituted. ++ */ ++public class DefaultParameterValueSubstitutor(val state: GenerationState) { ++ /** ++ * If all of the parameters of the specified constructor declare default values, ++ * generates a no-argument constructor that passes default values for all arguments. ++ */ ++ fun generateDefaultConstructorIfNeeded(constructorDescriptor: ConstructorDescriptor, ++ classBuilder: ClassBuilder, ++ context: CodegenContext<*>, ++ classOrObject: JetClassOrObject) { ++ if (!isEmptyConstructorNeeded(constructorDescriptor, classOrObject)) { ++ return ++ } ++ ++ generateOverloadWithSubstitutedParameters(constructorDescriptor, constructorDescriptor, classBuilder, classOrObject, ++ context, ++ constructorDescriptor.countDefaultParameters()) ++ } ++ ++ /** ++ * If the function is annotated with [kotlin.jvm.overloads], generates Java methods that ++ * have the default parameter values substituted. If a method has N parameters and M of which ++ * have default values, M overloads are generated: the first one takes N-1 parameters (all but ++ * the last one that takes a default value), the second takes N-2 parameters, and so on. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ */ ++ fun generateOverloadsIfNeeded(function: JetNamedFunction, ++ functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ owner: CodegenContext<*>, ++ classBuilder: ClassBuilder) { ++ val overloadsFqName = FqName.fromSegments(listOf(""kotlin"", ""jvm"", ""overloads"")) ++ if (functionDescriptor.getAnnotations().findAnnotation(overloadsFqName) == null) return ++ ++ val count = functionDescriptor.countDefaultParameters() ++ val context = owner.intoFunction(functionDescriptor) ++ ++ for (i in 1..count) { ++ generateOverloadWithSubstitutedParameters(functionDescriptor, delegateFunctionDescriptor, classBuilder, function, context, i) ++ } ++ } ++ ++ private fun FunctionDescriptor.countDefaultParameters() = ++ getValueParameters().count { it.hasDefaultValue() } ++ ++ /** ++ * Generates an overload for [functionDescriptor] that substitutes default values for the last ++ * [substituteCount] parameters that have default values. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ * @param methodElement the PSI element for the method implementation (used in diagnostic messages only) ++ */ ++ fun generateOverloadWithSubstitutedParameters(functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ classBuilder: ClassBuilder, ++ methodElement: JetElement?, ++ context: CodegenContext<*>, ++ substituteCount: Int) { ++ val isStatic = AsmUtil.isStaticMethod(context.getContextKind(), functionDescriptor) ++ val flags = AsmUtil.getVisibilityAccessFlag(functionDescriptor) or (if (isStatic) Opcodes.ACC_STATIC else 0) ++ val remainingParameters = getRemainingParameters(functionDescriptor.getOriginal(), substituteCount) ++ val signature = state.getTypeMapper().mapSignature(functionDescriptor, context.getContextKind(),","Please extract `state.getTypeMapper()` to a property +",2015-03-31 09:15:22 +354,"@@ -0,0 +1,204 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.codegen ++ ++import org.jetbrains.kotlin.codegen.binding.CodegenBinding ++import org.jetbrains.kotlin.codegen.context.CodegenContext ++import org.jetbrains.kotlin.codegen.state.GenerationState ++import org.jetbrains.kotlin.descriptors.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.JetClass ++import org.jetbrains.kotlin.psi.JetClassOrObject ++import org.jetbrains.kotlin.psi.JetElement ++import org.jetbrains.kotlin.psi.JetNamedFunction ++import org.jetbrains.kotlin.resolve.jvm.AsmTypes ++import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin ++import org.jetbrains.org.objectweb.asm.Opcodes ++import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter ++ ++/** ++ * Generates Java overloads for functions and constructors that have the default ++ * parameter values substituted. ++ */ ++public class DefaultParameterValueSubstitutor(val state: GenerationState) { ++ /** ++ * If all of the parameters of the specified constructor declare default values, ++ * generates a no-argument constructor that passes default values for all arguments. ++ */ ++ fun generateDefaultConstructorIfNeeded(constructorDescriptor: ConstructorDescriptor, ++ classBuilder: ClassBuilder, ++ context: CodegenContext<*>, ++ classOrObject: JetClassOrObject) { ++ if (!isEmptyConstructorNeeded(constructorDescriptor, classOrObject)) { ++ return ++ } ++ ++ generateOverloadWithSubstitutedParameters(constructorDescriptor, constructorDescriptor, classBuilder, classOrObject, ++ context, ++ constructorDescriptor.countDefaultParameters()) ++ } ++ ++ /** ++ * If the function is annotated with [kotlin.jvm.overloads], generates Java methods that ++ * have the default parameter values substituted. If a method has N parameters and M of which ++ * have default values, M overloads are generated: the first one takes N-1 parameters (all but ++ * the last one that takes a default value), the second takes N-2 parameters, and so on. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ */ ++ fun generateOverloadsIfNeeded(function: JetNamedFunction, ++ functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ owner: CodegenContext<*>, ++ classBuilder: ClassBuilder) { ++ val overloadsFqName = FqName.fromSegments(listOf(""kotlin"", ""jvm"", ""overloads"")) ++ if (functionDescriptor.getAnnotations().findAnnotation(overloadsFqName) == null) return ++ ++ val count = functionDescriptor.countDefaultParameters() ++ val context = owner.intoFunction(functionDescriptor) ++ ++ for (i in 1..count) { ++ generateOverloadWithSubstitutedParameters(functionDescriptor, delegateFunctionDescriptor, classBuilder, function, context, i) ++ } ++ } ++ ++ private fun FunctionDescriptor.countDefaultParameters() = ++ getValueParameters().count { it.hasDefaultValue() } ++ ++ /** ++ * Generates an overload for [functionDescriptor] that substitutes default values for the last ++ * [substituteCount] parameters that have default values. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ * @param methodElement the PSI element for the method implementation (used in diagnostic messages only) ++ */ ++ fun generateOverloadWithSubstitutedParameters(functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ classBuilder: ClassBuilder, ++ methodElement: JetElement?, ++ context: CodegenContext<*>, ++ substituteCount: Int) { ++ val isStatic = AsmUtil.isStaticMethod(context.getContextKind(), functionDescriptor) ++ val flags = AsmUtil.getVisibilityAccessFlag(functionDescriptor) or (if (isStatic) Opcodes.ACC_STATIC else 0) ++ val remainingParameters = getRemainingParameters(functionDescriptor.getOriginal(), substituteCount) ++ val signature = state.getTypeMapper().mapSignature(functionDescriptor, context.getContextKind(), ++ remainingParameters) ++ val mv = classBuilder.newMethod(OtherOrigin(functionDescriptor), flags, ++ signature.getAsmMethod().getName(), ++ signature.getAsmMethod().getDescriptor(), null, ++ FunctionCodegen.getThrownExceptions(functionDescriptor, state.getTypeMapper())) ++ ++ if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return ++ ++ val frameMap = FrameMap() ++ val v = InstructionAdapter(mv) ++ mv.visitCode() ++ ++ val methodOwner = state.getTypeMapper().mapToCallableMethod(delegateFunctionDescriptor, false, context).getOwner() ++ if (!isStatic) { ++ frameMap.enterTemp(AsmTypes.OBJECT_TYPE) ++ v.load(0, methodOwner) // Load this on stack","Maybe use the value returned by `enterTemp` instead of `0` for better readability +",2015-03-31 09:38:38 +352,"@@ -0,0 +1,204 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.codegen ++ ++import org.jetbrains.kotlin.codegen.binding.CodegenBinding ++import org.jetbrains.kotlin.codegen.context.CodegenContext ++import org.jetbrains.kotlin.codegen.state.GenerationState ++import org.jetbrains.kotlin.descriptors.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.JetClass ++import org.jetbrains.kotlin.psi.JetClassOrObject ++import org.jetbrains.kotlin.psi.JetElement ++import org.jetbrains.kotlin.psi.JetNamedFunction ++import org.jetbrains.kotlin.resolve.jvm.AsmTypes ++import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin ++import org.jetbrains.org.objectweb.asm.Opcodes ++import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter ++ ++/** ++ * Generates Java overloads for functions and constructors that have the default ++ * parameter values substituted. ++ */ ++public class DefaultParameterValueSubstitutor(val state: GenerationState) { ++ /** ++ * If all of the parameters of the specified constructor declare default values, ++ * generates a no-argument constructor that passes default values for all arguments. ++ */ ++ fun generateDefaultConstructorIfNeeded(constructorDescriptor: ConstructorDescriptor, ++ classBuilder: ClassBuilder, ++ context: CodegenContext<*>, ++ classOrObject: JetClassOrObject) { ++ if (!isEmptyConstructorNeeded(constructorDescriptor, classOrObject)) { ++ return ++ } ++ ++ generateOverloadWithSubstitutedParameters(constructorDescriptor, constructorDescriptor, classBuilder, classOrObject, ++ context, ++ constructorDescriptor.countDefaultParameters()) ++ } ++ ++ /** ++ * If the function is annotated with [kotlin.jvm.overloads], generates Java methods that ++ * have the default parameter values substituted. If a method has N parameters and M of which ++ * have default values, M overloads are generated: the first one takes N-1 parameters (all but ++ * the last one that takes a default value), the second takes N-2 parameters, and so on. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ */ ++ fun generateOverloadsIfNeeded(function: JetNamedFunction, ++ functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ owner: CodegenContext<*>, ++ classBuilder: ClassBuilder) { ++ val overloadsFqName = FqName.fromSegments(listOf(""kotlin"", ""jvm"", ""overloads"")) ++ if (functionDescriptor.getAnnotations().findAnnotation(overloadsFqName) == null) return ++ ++ val count = functionDescriptor.countDefaultParameters() ++ val context = owner.intoFunction(functionDescriptor) ++ ++ for (i in 1..count) { ++ generateOverloadWithSubstitutedParameters(functionDescriptor, delegateFunctionDescriptor, classBuilder, function, context, i) ++ } ++ } ++ ++ private fun FunctionDescriptor.countDefaultParameters() = ++ getValueParameters().count { it.hasDefaultValue() } ++ ++ /** ++ * Generates an overload for [functionDescriptor] that substitutes default values for the last ++ * [substituteCount] parameters that have default values. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ * @param methodElement the PSI element for the method implementation (used in diagnostic messages only) ++ */ ++ fun generateOverloadWithSubstitutedParameters(functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ classBuilder: ClassBuilder, ++ methodElement: JetElement?, ++ context: CodegenContext<*>, ++ substituteCount: Int) { ++ val isStatic = AsmUtil.isStaticMethod(context.getContextKind(), functionDescriptor) ++ val flags = AsmUtil.getVisibilityAccessFlag(functionDescriptor) or (if (isStatic) Opcodes.ACC_STATIC else 0) ++ val remainingParameters = getRemainingParameters(functionDescriptor.getOriginal(), substituteCount) ++ val signature = state.getTypeMapper().mapSignature(functionDescriptor, context.getContextKind(), ++ remainingParameters) ++ val mv = classBuilder.newMethod(OtherOrigin(functionDescriptor), flags, ++ signature.getAsmMethod().getName(), ++ signature.getAsmMethod().getDescriptor(), null, ++ FunctionCodegen.getThrownExceptions(functionDescriptor, state.getTypeMapper())) ++ ++ if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return ++ ++ val frameMap = FrameMap() ++ val v = InstructionAdapter(mv) ++ mv.visitCode() ++ ++ val methodOwner = state.getTypeMapper().mapToCallableMethod(delegateFunctionDescriptor, false, context).getOwner() ++ if (!isStatic) { ++ frameMap.enterTemp(AsmTypes.OBJECT_TYPE) ++ v.load(0, methodOwner) // Load this on stack ++ } else {","`else` should be on the next line :) Several times in this file +",2015-03-31 09:16:13 +353,"@@ -0,0 +1,204 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.codegen ++ ++import org.jetbrains.kotlin.codegen.binding.CodegenBinding ++import org.jetbrains.kotlin.codegen.context.CodegenContext ++import org.jetbrains.kotlin.codegen.state.GenerationState ++import org.jetbrains.kotlin.descriptors.* ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.JetClass ++import org.jetbrains.kotlin.psi.JetClassOrObject ++import org.jetbrains.kotlin.psi.JetElement ++import org.jetbrains.kotlin.psi.JetNamedFunction ++import org.jetbrains.kotlin.resolve.jvm.AsmTypes ++import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin ++import org.jetbrains.org.objectweb.asm.Opcodes ++import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter ++ ++/** ++ * Generates Java overloads for functions and constructors that have the default ++ * parameter values substituted. ++ */ ++public class DefaultParameterValueSubstitutor(val state: GenerationState) { ++ /** ++ * If all of the parameters of the specified constructor declare default values, ++ * generates a no-argument constructor that passes default values for all arguments. ++ */ ++ fun generateDefaultConstructorIfNeeded(constructorDescriptor: ConstructorDescriptor, ++ classBuilder: ClassBuilder, ++ context: CodegenContext<*>, ++ classOrObject: JetClassOrObject) { ++ if (!isEmptyConstructorNeeded(constructorDescriptor, classOrObject)) { ++ return ++ } ++ ++ generateOverloadWithSubstitutedParameters(constructorDescriptor, constructorDescriptor, classBuilder, classOrObject, ++ context, ++ constructorDescriptor.countDefaultParameters()) ++ } ++ ++ /** ++ * If the function is annotated with [kotlin.jvm.overloads], generates Java methods that ++ * have the default parameter values substituted. If a method has N parameters and M of which ++ * have default values, M overloads are generated: the first one takes N-1 parameters (all but ++ * the last one that takes a default value), the second takes N-2 parameters, and so on. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ */ ++ fun generateOverloadsIfNeeded(function: JetNamedFunction, ++ functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ owner: CodegenContext<*>, ++ classBuilder: ClassBuilder) { ++ val overloadsFqName = FqName.fromSegments(listOf(""kotlin"", ""jvm"", ""overloads"")) ++ if (functionDescriptor.getAnnotations().findAnnotation(overloadsFqName) == null) return ++ ++ val count = functionDescriptor.countDefaultParameters() ++ val context = owner.intoFunction(functionDescriptor) ++ ++ for (i in 1..count) { ++ generateOverloadWithSubstitutedParameters(functionDescriptor, delegateFunctionDescriptor, classBuilder, function, context, i) ++ } ++ } ++ ++ private fun FunctionDescriptor.countDefaultParameters() = ++ getValueParameters().count { it.hasDefaultValue() } ++ ++ /** ++ * Generates an overload for [functionDescriptor] that substitutes default values for the last ++ * [substituteCount] parameters that have default values. ++ * ++ * @param functionDescriptor the method for which the overloads are generated ++ * @param delegateFunctionDescriptor the method descriptor for the implementation that we need to call ++ * (same as [functionDescriptor] in all cases except for companion object methods annotated with [platformStatic], ++ * where [functionDescriptor] is the static method in the main class and [delegateFunctionDescriptor] is the ++ * implementation in the companion object class) ++ * @param methodElement the PSI element for the method implementation (used in diagnostic messages only) ++ */ ++ fun generateOverloadWithSubstitutedParameters(functionDescriptor: FunctionDescriptor, ++ delegateFunctionDescriptor: FunctionDescriptor, ++ classBuilder: ClassBuilder, ++ methodElement: JetElement?, ++ context: CodegenContext<*>, ++ substituteCount: Int) { ++ val isStatic = AsmUtil.isStaticMethod(context.getContextKind(), functionDescriptor) ++ val flags = AsmUtil.getVisibilityAccessFlag(functionDescriptor) or (if (isStatic) Opcodes.ACC_STATIC else 0) ++ val remainingParameters = getRemainingParameters(functionDescriptor.getOriginal(), substituteCount) ++ val signature = state.getTypeMapper().mapSignature(functionDescriptor, context.getContextKind(), ++ remainingParameters) ++ val mv = classBuilder.newMethod(OtherOrigin(functionDescriptor), flags, ++ signature.getAsmMethod().getName(), ++ signature.getAsmMethod().getDescriptor(), null, ++ FunctionCodegen.getThrownExceptions(functionDescriptor, state.getTypeMapper())) ++ ++ if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return ++ ++ val frameMap = FrameMap() ++ val v = InstructionAdapter(mv) ++ mv.visitCode() ++ ++ val methodOwner = state.getTypeMapper().mapToCallableMethod(delegateFunctionDescriptor, false, context).getOwner() ++ if (!isStatic) { ++ frameMap.enterTemp(AsmTypes.OBJECT_TYPE) ++ v.load(0, methodOwner) // Load this on stack ++ } else { ++ val delegateOwner = delegateFunctionDescriptor.getContainingDeclaration() ++ if (delegateOwner is ClassDescriptor && delegateOwner.isCompanionObject()) { ++ val singletonValue = StackValue.singleton(delegateOwner, state.getTypeMapper()) ++ singletonValue.put(singletonValue.type, v); ++ } ++ } ++ ++ val receiver = functionDescriptor.getExtensionReceiverParameter() ++ if (receiver != null) { ++ val receiverType = state.getTypeMapper().mapType(receiver) ++ val receiverIndex = frameMap.enter(receiver, receiverType) ++ StackValue.local(receiverIndex, receiverType).put(receiverType, v) ++ } ++ remainingParameters.forEach { ++ frameMap.enter(it, state.getTypeMapper().mapType(it)) ++ } ++ ++ var mask = 0 ++ val masks = arrayListOf() ++ for (parameterDescriptor in functionDescriptor.getValueParameters()) { ++ val paramType = state.getTypeMapper().mapType(parameterDescriptor.getType()) ++ if (parameterDescriptor in remainingParameters) { ++ val index = frameMap.getIndex(parameterDescriptor) ++ val type = state.getTypeMapper().mapType(parameterDescriptor)","Already calculated a little earlier (`paramType`) +",2015-03-31 09:18:17 +728,"@@ -0,0 +1,205 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.jvm.compiler ++ ++import com.intellij.testFramework.TestDataPath ++import org.jetbrains.kotlin.test.JUnit3RunnerWithInners ++import org.jetbrains.kotlin.test.KotlinTestUtils ++import org.jetbrains.kotlin.test.TestMetadata ++import org.junit.runner.RunWith ++ ++@SuppressWarnings(""all"") ++@TestMetadata(""compiler/testData/compileKotlinAgainstJava"") ++@TestDataPath(""\$PROJECT_ROOT"") ++@RunWith(JUnit3RunnerWithInners::class) ++class CompileKotlinAgainstJavaTest : AbstractCompileJavaAgainstKotlinTest() {",`CompileKotlinAgainstJava` but `AbstractCompilerJavaAgainstKotlin`? Looks very strange,2017-04-05 15:33:28 +39,"@@ -0,0 +1,207 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.ClassDescriptor; ++import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class MapPlatformClassToKotlinFix extends JetIntentionAction { ++ private static final String PRIMARY_USAGE = ""PrimaryUsage""; ++ private static final String OTHER_USAGE = ""OtherUsage""; ++ ++ private final ClassDescriptor platformClass; ++ private final Collection possibleClasses; ++ ++ public MapPlatformClassToKotlinFix(@NotNull JetReferenceExpression element, @NotNull ClassDescriptor platformClass, ++ @NotNull Collection possibleClasses) { ++ super(element); ++ this.platformClass = platformClass; ++ this.possibleClasses = possibleClasses; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ ++ String platformClassQualifiedName = DescriptorRenderer.TEXT.renderType(platformClass.getDefaultType()); ++ return possibleClasses.size() == 1 ++ ? JetBundle.message(""map.platform.class.to.kotlin"", platformClassQualifiedName, ++ DescriptorRenderer.TEXT.renderType(possibleClasses.iterator().next().getDefaultType())) ++ : JetBundle.message(""map.platform.class.to.kotlin.multiple"", platformClassQualifiedName); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""map.platform.class.to.kotlin.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {","This method is pretty long. Consider extracting methods for it. First candidate for extracting is code about live template in the end of the method. +",2013-02-28 14:33:59 +37,"@@ -0,0 +1,207 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.ClassDescriptor; ++import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class MapPlatformClassToKotlinFix extends JetIntentionAction { ++ private static final String PRIMARY_USAGE = ""PrimaryUsage""; ++ private static final String OTHER_USAGE = ""OtherUsage""; ++ ++ private final ClassDescriptor platformClass; ++ private final Collection possibleClasses; ++ ++ public MapPlatformClassToKotlinFix(@NotNull JetReferenceExpression element, @NotNull ClassDescriptor platformClass, ++ @NotNull Collection possibleClasses) { ++ super(element); ++ this.platformClass = platformClass; ++ this.possibleClasses = possibleClasses; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ ++ String platformClassQualifiedName = DescriptorRenderer.TEXT.renderType(platformClass.getDefaultType()); ++ return possibleClasses.size() == 1 ++ ? JetBundle.message(""map.platform.class.to.kotlin"", platformClassQualifiedName, ++ DescriptorRenderer.TEXT.renderType(possibleClasses.iterator().next().getDefaultType())) ++ : JetBundle.message(""map.platform.class.to.kotlin.multiple"", platformClassQualifiedName); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""map.platform.class.to.kotlin.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ BindingContext context = KotlinCacheManager.getInstance(project).getDeclarationsFromProject().getBindingContext(); ++ Collection diagnostics = context.getDiagnostics(); ++ List imports = new ArrayList(); ++ List usages = new ArrayList(); ++ ++ for (Diagnostic diagnostic : diagnostics) { ++ if (diagnostic.getFactory() != Errors.PLATFORM_CLASS_MAPPED_TO_KOTLIN) continue; ++ JetReferenceExpression refExpr = getImportOrUsageFromDiagnostic(diagnostic); ++ if (refExpr == null) continue; ++ DeclarationDescriptor descriptor = context.get(BindingContext.REFERENCE_TARGET, refExpr); ++ if (descriptor == null || !(descriptor.equals(platformClass))) continue;","Is this check necessary? Maybe remove it or replace with assert? +",2013-02-28 14:17:57 +38,"@@ -0,0 +1,207 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.ClassDescriptor; ++import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class MapPlatformClassToKotlinFix extends JetIntentionAction { ++ private static final String PRIMARY_USAGE = ""PrimaryUsage""; ++ private static final String OTHER_USAGE = ""OtherUsage""; ++ ++ private final ClassDescriptor platformClass; ++ private final Collection possibleClasses; ++ ++ public MapPlatformClassToKotlinFix(@NotNull JetReferenceExpression element, @NotNull ClassDescriptor platformClass, ++ @NotNull Collection possibleClasses) { ++ super(element); ++ this.platformClass = platformClass; ++ this.possibleClasses = possibleClasses; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ ++ String platformClassQualifiedName = DescriptorRenderer.TEXT.renderType(platformClass.getDefaultType()); ++ return possibleClasses.size() == 1 ++ ? JetBundle.message(""map.platform.class.to.kotlin"", platformClassQualifiedName, ++ DescriptorRenderer.TEXT.renderType(possibleClasses.iterator().next().getDefaultType())) ++ : JetBundle.message(""map.platform.class.to.kotlin.multiple"", platformClassQualifiedName); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""map.platform.class.to.kotlin.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ BindingContext context = KotlinCacheManager.getInstance(project).getDeclarationsFromProject().getBindingContext(); ++ Collection diagnostics = context.getDiagnostics(); ++ List imports = new ArrayList(); ++ List usages = new ArrayList(); ++ ++ for (Diagnostic diagnostic : diagnostics) { ++ if (diagnostic.getFactory() != Errors.PLATFORM_CLASS_MAPPED_TO_KOTLIN) continue; ++ JetReferenceExpression refExpr = getImportOrUsageFromDiagnostic(diagnostic); ++ if (refExpr == null) continue; ++ DeclarationDescriptor descriptor = context.get(BindingContext.REFERENCE_TARGET, refExpr); ++ if (descriptor == null || !(descriptor.equals(platformClass))) continue; ++ JetImportDirective imp = PsiTreeUtil.getParentOfType(refExpr, JetImportDirective.class); ++ if (imp == null) { ++ JetUserType type = PsiTreeUtil.getParentOfType(refExpr, JetUserType.class); ++ if (type == null) continue; ++ usages.add(type); ++ } else { ++ imports.add(imp); ++ } ++ } ++ ++ ClassDescriptor replacementClass = possibleClasses.iterator().next(); ++ String replacementClassName = replacementClass.getName().getName(); ++ List replacedExpressions = new ArrayList(); ++ for (JetImportDirective imp : imports) { ++ imp.delete(); ++ } ++ for (JetUserType usage : usages) { ++ JetTypeArgumentList typeArguments = usage.getTypeArgumentList(); ++ String typeArgumentsString = typeArguments == null ? """" : typeArguments.getText(); ++ JetTypeReference replacementType = JetPsiFactory.createType(project, replacementClassName + typeArgumentsString); ++ JetTypeElement replacementTypeElement = replacementType.getTypeElement(); ++ assert replacementTypeElement != null; ++ PsiElement replacedElement = usage.replace(replacementTypeElement); ++ PsiElement replacedExpression = replacedElement.getFirstChild(); ++ assert replacedExpression instanceof JetSimpleNameExpression; // assumption: the Kotlin class requires no imports ++ replacedExpressions.add((JetExpression) replacedExpression); ++ } ++ ++ if (replacedExpressions.size() == 0) { // if we didn't replace any usages, there's no reason to even give a choice","This condition is equivalent to usages.isEmpty(), which is more straightforward and can be checked before loop. +",2013-02-28 14:22:46 +36,"@@ -0,0 +1,207 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.ClassDescriptor; ++import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.diagnostics.Errors; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; ++import org.jetbrains.jet.renderer.DescriptorRenderer; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class MapPlatformClassToKotlinFix extends JetIntentionAction { ++ private static final String PRIMARY_USAGE = ""PrimaryUsage""; ++ private static final String OTHER_USAGE = ""OtherUsage""; ++ ++ private final ClassDescriptor platformClass; ++ private final Collection possibleClasses; ++ ++ public MapPlatformClassToKotlinFix(@NotNull JetReferenceExpression element, @NotNull ClassDescriptor platformClass, ++ @NotNull Collection possibleClasses) { ++ super(element); ++ this.platformClass = platformClass; ++ this.possibleClasses = possibleClasses; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ ++ String platformClassQualifiedName = DescriptorRenderer.TEXT.renderType(platformClass.getDefaultType()); ++ return possibleClasses.size() == 1 ++ ? JetBundle.message(""map.platform.class.to.kotlin"", platformClassQualifiedName, ++ DescriptorRenderer.TEXT.renderType(possibleClasses.iterator().next().getDefaultType())) ++ : JetBundle.message(""map.platform.class.to.kotlin.multiple"", platformClassQualifiedName); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""map.platform.class.to.kotlin.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ BindingContext context = KotlinCacheManager.getInstance(project).getDeclarationsFromProject().getBindingContext(); ++ Collection diagnostics = context.getDiagnostics(); ++ List imports = new ArrayList(); ++ List usages = new ArrayList(); ++ ++ for (Diagnostic diagnostic : diagnostics) { ++ if (diagnostic.getFactory() != Errors.PLATFORM_CLASS_MAPPED_TO_KOTLIN) continue; ++ JetReferenceExpression refExpr = getImportOrUsageFromDiagnostic(diagnostic); ++ if (refExpr == null) continue; ++ DeclarationDescriptor descriptor = context.get(BindingContext.REFERENCE_TARGET, refExpr); ++ if (descriptor == null || !(descriptor.equals(platformClass))) continue; ++ JetImportDirective imp = PsiTreeUtil.getParentOfType(refExpr, JetImportDirective.class); ++ if (imp == null) { ++ JetUserType type = PsiTreeUtil.getParentOfType(refExpr, JetUserType.class); ++ if (type == null) continue; ++ usages.add(type); ++ } else { ++ imports.add(imp); ++ } ++ } ++ ++ ClassDescriptor replacementClass = possibleClasses.iterator().next(); ++ String replacementClassName = replacementClass.getName().getName(); ++ List replacedExpressions = new ArrayList(); ++ for (JetImportDirective imp : imports) { ++ imp.delete(); ++ } ++ for (JetUserType usage : usages) { ++ JetTypeArgumentList typeArguments = usage.getTypeArgumentList(); ++ String typeArgumentsString = typeArguments == null ? """" : typeArguments.getText(); ++ JetTypeReference replacementType = JetPsiFactory.createType(project, replacementClassName + typeArgumentsString); ++ JetTypeElement replacementTypeElement = replacementType.getTypeElement(); ++ assert replacementTypeElement != null; ++ PsiElement replacedElement = usage.replace(replacementTypeElement); ++ PsiElement replacedExpression = replacedElement.getFirstChild(); ++ assert replacedExpression instanceof JetSimpleNameExpression; // assumption: the Kotlin class requires no imports ++ replacedExpressions.add((JetExpression) replacedExpression); ++ } ++ ++ if (replacedExpressions.size() == 0) { // if we didn't replace any usages, there's no reason to even give a choice ++ return; ++ } ++ ++ if (possibleClasses.size() > 1) { ++ PsiDocumentManager.getInstance(project).commitAllDocuments(); ++ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); ++ ++ PsiElement primaryReplacedExpression = replacedExpressions.iterator().next(); ++ ++ final CaretModel caretModel = editor.getCaretModel(); ++ final int oldOffset = caretModel.getOffset(); ++ caretModel.moveToOffset(file.getNode().getStartOffset()); ++ ++ LinkedHashSet possibleTypes = new LinkedHashSet(); ++ for (ClassDescriptor klass : possibleClasses) { ++ possibleTypes.add(klass.getName().getName()); ++ } ++ ++ TemplateBuilderImpl builder = new TemplateBuilderImpl(file); ++ Expression expression = new MyLookupExpression(primaryReplacedExpression.getText(), possibleTypes, null, false, ++ JetBundle.message(""map.platform.class.to.kotlin.advertisement"")); ++ ++ builder.replaceElement(primaryReplacedExpression, PRIMARY_USAGE, expression, true); ++ for (PsiElement replacedExpression : replacedExpressions) { ++ if (replacedExpression == primaryReplacedExpression) continue; ++ builder.replaceElement(replacedExpression, OTHER_USAGE, PRIMARY_USAGE, false); ++ } ++ TemplateManager.getInstance(project).startTemplate(editor, builder.buildInlineTemplate(), new TemplateEditingAdapter() { ++ @Override ++ public void templateFinished(Template template, boolean brokenOff) { ++ caretModel.moveToOffset(oldOffset); ++ } ++ }); ++ } ++ } ++ ++ private static JetReferenceExpression getImportOrUsageFromDiagnostic(@NotNull Diagnostic diagnostic) { ++ JetImportDirective imp = QuickFixUtil.getParentElementOfType(diagnostic, JetImportDirective.class); ++ JetReferenceExpression typeExpr; ++ if (imp == null) { ++ JetUserType type = QuickFixUtil.getParentElementOfType(diagnostic, JetUserType.class); ++ if (type == null) return null; ++ typeExpr = type.getReferenceExpression(); ++ } else { ++ JetExpression importRef = imp.getImportedReference(); ++ if (importRef == null || !(importRef instanceof JetDotQualifiedExpression)) return null; ++ JetExpression refExpr = ((JetDotQualifiedExpression) importRef).getSelectorExpression(); ++ if (refExpr == null || !(refExpr instanceof JetReferenceExpression)) return null; ++ typeExpr = (JetReferenceExpression) refExpr; ++ } ++ return typeExpr; ++ } ++ ++ public static JetIntentionActionFactory createFactory() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ assert diagnostic.getFactory() instanceof DiagnosticFactory1; ++ ++ JetReferenceExpression typeExpr = getImportOrUsageFromDiagnostic(diagnostic); ++ if (typeExpr == null) return null; ++ ++ BindingContext context = KotlinCacheManager.getInstance(diagnostic.getPsiFile().getProject()).getDeclarationsFromProject().getBindingContext(); ++ DeclarationDescriptor descriptor = context.get(BindingContext.REFERENCE_TARGET, typeExpr); ++ if (descriptor == null || !(descriptor instanceof ClassDescriptor)) return null; ++ ClassDescriptor platformClass = (ClassDescriptor) descriptor; ++ ++ @SuppressWarnings(""unchecked"") ++ DiagnosticWithParameters1 parametrizedDiagnostic = (DiagnosticWithParameters1) diagnostic;","All the boilerplate starting from this line can be avoided by casting to DiagnosticWithParameters1> instead of raw type. +",2013-02-28 14:15:00 +663,"@@ -0,0 +1,208 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.j2k ++ ++import com.intellij.psi.CommonClassNames.* ++import com.intellij.psi.PsiField ++import org.jetbrains.kotlin.builtins.PrimitiveType ++import org.jetbrains.kotlin.j2k.ast.Expression ++import org.jetbrains.kotlin.j2k.ast.Identifier ++import org.jetbrains.kotlin.j2k.ast.QualifiedExpression ++ ++enum class SpecialFiled(val qualifiedClassName: String?, val fieldName: String) {","SpecialField +",2016-12-27 11:41:21 +664,"@@ -0,0 +1,208 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.j2k ++ ++import com.intellij.psi.CommonClassNames.* ++import com.intellij.psi.PsiField ++import org.jetbrains.kotlin.builtins.PrimitiveType ++import org.jetbrains.kotlin.j2k.ast.Expression ++import org.jetbrains.kotlin.j2k.ast.Identifier ++import org.jetbrains.kotlin.j2k.ast.QualifiedExpression ++ ++enum class SpecialFiled(val qualifiedClassName: String?, val fieldName: String) { ++ ++ BYTE_MAX_VALUE(JAVA_LANG_BYTE, ""MAX_VALUE"") {","You should not hard-code all possible constants. +",2016-12-27 11:43:40 +605,"@@ -0,0 +1,21 @@ ++//method","You need to include the generated test class into your commit. +",2016-09-12 18:37:57 +604,"@@ -0,0 +1,21 @@ ++//method ++void foo() {","Please try to ensure that testdata files are valid Java code. This file does not compile ('status' is undefined, the types do not match, etc.) +",2016-09-12 18:37:39 +607,"@@ -0,0 +1,21 @@ ++//method ++void foo() { ++ switch (status) { ++ case ""init"": ++ case ""dial"": ++ case ""transmit"": ++ return Color.BLACK; ++ ++ case ""ok"": ++ return 0xFF006600; ++ ++ case ""cancel"": ++ return 0xFF666666; ++ ++ case ""fail"": ++ case ""busy"": ++ case ""error"":","Please add a test for the case when 'default' is in the middle of the list of other cases (`case ""error"": default: case ""busy:""`) and make sure that this test passes. +",2016-09-12 18:40:50 +210,"@@ -0,0 +1,212 @@ ++/* ++* Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lang.psi.JetPostfixExpression ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lexer.JetTokens ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetElement ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector ++import com.intellij.psi.util.PsiTreeUtil ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns ++import org.jetbrains.jet.lang.psi.JetFile ++ ++public class OperatorToFunctionIntention : JetSelfTargetingIntention(""operator.to.function"", javaClass()) { ++ fun isApplicablePrefix(element: JetPrefixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS, JetTokens.EXCL -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicablePostfix(element: JetPostfixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUSPLUS, JetTokens.MINUSMINUS -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicableBinary(element: JetBinaryExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.MUL, JetTokens.DIV, JetTokens.PERC, JetTokens.RANGE, JetTokens.IN_KEYWORD, JetTokens.NOT_IN, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.GT, JetTokens.LT, JetTokens.GTEQ, JetTokens.LTEQ -> true ++ JetTokens.EQ -> element.getLeft() is JetArrayAccessExpression ++ else -> false ++ } ++ } ++ ++ fun isApplicableArrayAccess(element: JetArrayAccessExpression): Boolean { ++ return true ++ } ++ ++ fun isApplicableCall(element: JetCallExpression): Boolean { ++ //element.getCalleeExpression()?.getClass()?.getMethods()?.forEach{println(""element has method "" + it.getName())} ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val calleeClass = context[BindingContext.CLASS, element.getCalleeExpression()] ++ //println(""calleeClass is "" + calleeClass?.getName()) ++ //calleeClass.javaClass.getMethods().forEach { println(""element has method "" + it.getName()) } ++ return element.getParent() !is JetDotQualifiedExpression && element.getValueArgumentList() != null","Basically, we need to retrieve ResolvedCall corresponding to call of interest and check if resulting function is `invoke`. + +``` +val resolvedCall = AnalyzerFacadeWithCache.getContextForElement(element)[BindingContext.RESOLVED_CALL, element.getCalleeExpression()] +val descriptor = resolvedCall?.getResultingDescriptor() +if (descriptor is FunctionDescriptor && descriptor.getName().asString == ""invoke"") { + // do whatever we need +} +``` +",2014-04-23 14:19:59 +209,"@@ -0,0 +1,212 @@ ++/* ++* Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lang.psi.JetPostfixExpression ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lexer.JetTokens ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetElement ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector ++import com.intellij.psi.util.PsiTreeUtil ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns ++import org.jetbrains.jet.lang.psi.JetFile ++ ++public class OperatorToFunctionIntention : JetSelfTargetingIntention(""operator.to.function"", javaClass()) { ++ fun isApplicablePrefix(element: JetPrefixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS, JetTokens.EXCL -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicablePostfix(element: JetPostfixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUSPLUS, JetTokens.MINUSMINUS -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicableBinary(element: JetBinaryExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.MUL, JetTokens.DIV, JetTokens.PERC, JetTokens.RANGE, JetTokens.IN_KEYWORD, JetTokens.NOT_IN, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.GT, JetTokens.LT, JetTokens.GTEQ, JetTokens.LTEQ -> true ++ JetTokens.EQ -> element.getLeft() is JetArrayAccessExpression ++ else -> false ++ } ++ } ++ ++ fun isApplicableArrayAccess(element: JetArrayAccessExpression): Boolean { ++ return true ++ } ++ ++ fun isApplicableCall(element: JetCallExpression): Boolean { ++ //element.getCalleeExpression()?.getClass()?.getMethods()?.forEach{println(""element has method "" + it.getName())} ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val calleeClass = context[BindingContext.CLASS, element.getCalleeExpression()] ++ //println(""calleeClass is "" + calleeClass?.getName()) ++ //calleeClass.javaClass.getMethods().forEach { println(""element has method "" + it.getName()) } ++ return element.getParent() !is JetDotQualifiedExpression && element.getValueArgumentList() != null ++ } ++ ++ override fun isApplicableTo(element: JetExpression): Boolean { ++ return when (element) { ++ is JetPrefixExpression -> isApplicablePrefix(element) ++ is JetPostfixExpression -> isApplicablePostfix(element) ++ is JetBinaryExpression -> isApplicableBinary(element) ++ is JetArrayAccessExpression -> isApplicableArrayAccess(element) ++ is JetCallExpression -> isApplicableCall(element) ++ else -> false ++ } ++ } ++ ++ ++ fun convertPrefix(element: JetPrefixExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val base = element.getBaseExpression()!!.getText() ++ ++ val call = when (op) { ++ JetTokens.PLUS -> ""plus()"" ++ JetTokens.MINUS -> ""minus()"" ++ JetTokens.PLUSPLUS -> ""inc()"" ++ JetTokens.MINUSMINUS -> ""dec()"" ++ JetTokens.EXCL -> ""not()"" ++ else -> return ++ } ++ ++ val transformation = ""$base.$call"" ++ val transformed = JetPsiFactory.createExpression(element.getProject(), transformation) ++ element.replace(transformed) ++ } ++ ++ fun convertPostFix(element: JetPostfixExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val base = element.getBaseExpression()!!.getText() ++ ++ val call = when (op) { ++ JetTokens.PLUSPLUS -> ""inc()"" ++ JetTokens.MINUSMINUS -> ""dec()"" ++ else -> return ++ } ++ ++ val transformation = ""$base.$call"" ++ val transformed = JetPsiFactory.createExpression(element.getProject(), transformation) ++ element.replace(transformed) ++ } ++ ++ fun convertBinary(element: JetBinaryExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val left = element.getLeft()!! ++ val right = element.getRight()!! ++ val leftText = left.getText() ++ val rightText = right.getText() ++ ++ if (op == JetTokens.EQ) { ++ if (left is JetArrayAccessExpression) { ++ convertArrayAccess(left as JetArrayAccessExpression) ++ } ++ return ++ } ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext()","This function is not available anymore. Please, rebase against current master and use `AnalyzerFacadeWithCache.getContextForElement(element)` instead +",2014-04-23 13:44:30 +208,"@@ -0,0 +1,212 @@ ++/* ++* Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lang.psi.JetPostfixExpression ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lexer.JetTokens ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetElement ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector ++import com.intellij.psi.util.PsiTreeUtil ++import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns ++import org.jetbrains.jet.lang.psi.JetFile ++ ++public class OperatorToFunctionIntention : JetSelfTargetingIntention(""operator.to.function"", javaClass()) { ++ fun isApplicablePrefix(element: JetPrefixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS, JetTokens.EXCL -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicablePostfix(element: JetPostfixExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUSPLUS, JetTokens.MINUSMINUS -> true ++ else -> false ++ } ++ } ++ ++ fun isApplicableBinary(element: JetBinaryExpression): Boolean { ++ return when (element.getOperationReference().getReferencedNameElementType()) { ++ JetTokens.PLUS, JetTokens.MINUS, JetTokens.MUL, JetTokens.DIV, JetTokens.PERC, JetTokens.RANGE, JetTokens.IN_KEYWORD, JetTokens.NOT_IN, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.GT, JetTokens.LT, JetTokens.GTEQ, JetTokens.LTEQ -> true ++ JetTokens.EQ -> element.getLeft() is JetArrayAccessExpression ++ else -> false ++ } ++ } ++ ++ fun isApplicableArrayAccess(element: JetArrayAccessExpression): Boolean { ++ return true ++ } ++ ++ fun isApplicableCall(element: JetCallExpression): Boolean { ++ //element.getCalleeExpression()?.getClass()?.getMethods()?.forEach{println(""element has method "" + it.getName())} ++ //val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ //val calleeClass = context[BindingContext.CLASS, element.getCalleeExpression()] ++ //println(""calleeClass is "" + calleeClass?.getName()) ++ //calleeClass.javaClass.getMethods().forEach { println(""element has method "" + it.getName()) } ++ return element.getParent() !is JetDotQualifiedExpression && element.getValueArgumentList() != null ++ } ++ ++ override fun isApplicableTo(element: JetExpression): Boolean { ++ return when (element) { ++ is JetPrefixExpression -> isApplicablePrefix(element) ++ is JetPostfixExpression -> isApplicablePostfix(element) ++ is JetBinaryExpression -> isApplicableBinary(element) ++ is JetArrayAccessExpression -> isApplicableArrayAccess(element) ++ is JetCallExpression -> isApplicableCall(element) ++ else -> false ++ } ++ } ++ ++ ++ fun convertPrefix(element: JetPrefixExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val base = element.getBaseExpression()!!.getText() ++ ++ val call = when (op) { ++ JetTokens.PLUS -> ""plus()"" ++ JetTokens.MINUS -> ""minus()"" ++ JetTokens.PLUSPLUS -> ""inc()"" ++ JetTokens.MINUSMINUS -> ""dec()"" ++ JetTokens.EXCL -> ""not()"" ++ else -> return ++ } ++ ++ val transformation = ""$base.$call"" ++ val transformed = JetPsiFactory.createExpression(element.getProject(), transformation) ++ element.replace(transformed) ++ } ++ ++ fun convertPostFix(element: JetPostfixExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val base = element.getBaseExpression()!!.getText() ++ ++ val call = when (op) { ++ JetTokens.PLUSPLUS -> ""inc()"" ++ JetTokens.MINUSMINUS -> ""dec()"" ++ else -> return ++ } ++ ++ val transformation = ""$base.$call"" ++ val transformed = JetPsiFactory.createExpression(element.getProject(), transformation) ++ element.replace(transformed) ++ } ++ ++ fun convertBinary(element: JetBinaryExpression) { ++ val op = element.getOperationReference().getReferencedNameElementType() ++ val left = element.getLeft()!! ++ val right = element.getRight()!! ++ val leftText = left.getText() ++ val rightText = right.getText() ++ ++ if (op == JetTokens.EQ) { ++ if (left is JetArrayAccessExpression) { ++ convertArrayAccess(left as JetArrayAccessExpression) ++ } ++ return ++ } ++ ++ val context = AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingFile() as JetFile).getBindingContext() ++ val functionCandidate = context[BindingContext.RESOLVED_CALL, element.getOperationReference()] ++ val functionName = functionCandidate?.getCandidateDescriptor()?.getName().toString() ++ ++ val elemType = context[BindingContext.EXPRESSION_TYPE, left] ++ ++ ++ val transformation = when (op) { ++ JetTokens.PLUS -> ""$leftText.plus($rightText)"" ++ JetTokens.MINUS -> ""$leftText.minus($rightText)"" ++ JetTokens.MUL -> ""$leftText.times($rightText)"" ++ JetTokens.DIV -> ""$leftText.div($rightText)"" ++ JetTokens.PERC -> ""$leftText.mod($rightText)"" ++ JetTokens.RANGE -> ""$leftText.rangeTo($rightText)"" ++ JetTokens.IN_KEYWORD -> ""$rightText.contains($leftText)"" ++ JetTokens.NOT_IN -> ""!$rightText.contains($leftText)"" ++ JetTokens.PLUSEQ -> if (functionName == ""plusAssign"") ""$leftText.plusAssign($rightText)"" else ""$leftText = $leftText.plus($rightText)"" ++ JetTokens.MINUSEQ -> if (functionName == ""minusAssign"") ""$leftText.minusAssign($rightText)"" else ""$leftText = $leftText.minus($rightText)"" ++ JetTokens.MULTEQ -> if (functionName == ""multAssign"") ""$leftText.multAssign($rightText)"" else ""$leftText = $leftText.mult($rightText)"" ++ JetTokens.DIVEQ -> if (functionName == ""divAssign"") ""$leftText.divAssign($rightText)"" else ""$leftText = $leftText.div($rightText)"" ++ JetTokens.PERCEQ -> if (functionName == ""modAssign"") ""$leftText.modAssign($rightText)"" else ""$leftText = $leftText.mod($rightText)"" ++ JetTokens.EQEQ -> (if (elemType?.isNullable() ?: true) ""$leftText?."" else ""$leftText."") + ""equals($rightText) ?: $rightText.identityEquals(null)""","It still produces unnecessary code. If `a` has a non-nullable type, `a == b` should be replaced by `a.equals(b)`, not `a.equals(b) ?: b.identityEquals(null)` +",2014-04-23 13:40:13 +486,"@@ -0,0 +1,22 @@ ++package demo ++ ++import com.google.common.primitives.Ints ++import com.google.common.base.Joiner ++import java.util.ArrayList ++ ++class KotlinGreetingJoiner(val greeter : Greeter) { ++ ++ val names = ArrayList() ++ ++ fun addName(name : String?): Unit{ ++ names.add(name) ++ } ++ ++ fun getJoinedGreeting() : String? { ++ val joiner = Joiner.on("" and "").skipNulls();","why do we need guava in such simple example? we can replace ugly `Joiner.on("" and "").skipNulls().join(names)` with `names.filterNotNull().joinToString("" and "")`. We also don't need `com.google.common.primitives.Ints` at all... +",2015-10-28 13:11:42 +705,"@@ -0,0 +1,227 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.JavacClass ++import org.jetbrains.kotlin.wrappers.symbols.JavacPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.wrappers.trees.JCClass ++import org.jetbrains.kotlin.wrappers.trees.JCPackage ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.TypeElement ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class Javac(javaFiles: Collection,",May be `JavaCompilerWrapper`?,2017-04-05 13:04:43 +706,"@@ -0,0 +1,227 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.JavacClass ++import org.jetbrains.kotlin.wrappers.symbols.JavacPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.wrappers.trees.JCClass ++import org.jetbrains.kotlin.wrappers.trees.JCPackage ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.TypeElement ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class Javac(javaFiles: Collection, ++ classPathRoots: List, ++ outDir: File?, ++ private val messageCollector: MessageCollector?, ++ arguments: Array?) : Closeable { ++ ++ companion object { ++ fun getInstance(project: Project): Javac = ServiceManager.getService(project, Javac::class.java) ++ } ++ ++ val JAVA_LANG_OBJECT by lazy { findClassInSymbols(CommonClassNames.JAVA_LANG_OBJECT) } ++ ++ private val context = Context() ++ ++ init { ++ messageCollector?.let { JavacLogger.preRegister(context, it) } ++ arguments?.toList()?.let { JavacOptionsMapper.map(Options.instance(context), it) } ++ } ++ ++ private val javac = object : JavaCompiler(context) { ++ override fun parseFiles(files: Iterable?) = compilationUnits ++ } ++ private val fileManager = context[JavaFileManager::class.java] as JavacFileManager ++ ++ init { ++ fileManager.setLocation(StandardLocation.CLASS_PATH, classPathRoots) ++ outDir?.let { ++ it.mkdirs() ++ fileManager.setLocation(StandardLocation.CLASS_OUTPUT, listOf(it)) ++ } ++ } ++ ++ private val symbols = Symtab.instance(context) ++ private val trees = JavacTrees.instance(context) ++ private val elements = JavacElements.instance(context) ++ private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList() ++ private val compilationUnits: JavacList = fileObjects.map(javac::parse).toJavacList() ++ ++ private val javaClasses = compilationUnits ++ .flatMap { unit -> unit.typeDecls ++ .flatMap { JCClass(it as JCTree.JCClassDecl, trees.getPath(unit, it), this).withInnerClasses() } ++ } ++ .map { it.fqName to it } ++ .toMap()",There is `keysToMap` in Kotlin project itself & also `associateBy` in stdlib. I'm not sure it's quite important but they may be faster (one internal container instead of two) and definitely shorter.,2017-04-05 13:08:29 +707,"@@ -0,0 +1,227 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.JavacClass ++import org.jetbrains.kotlin.wrappers.symbols.JavacPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.wrappers.trees.JCClass ++import org.jetbrains.kotlin.wrappers.trees.JCPackage ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.TypeElement ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class Javac(javaFiles: Collection, ++ classPathRoots: List, ++ outDir: File?, ++ private val messageCollector: MessageCollector?, ++ arguments: Array?) : Closeable { ++ ++ companion object { ++ fun getInstance(project: Project): Javac = ServiceManager.getService(project, Javac::class.java) ++ } ++ ++ val JAVA_LANG_OBJECT by lazy { findClassInSymbols(CommonClassNames.JAVA_LANG_OBJECT) } ++ ++ private val context = Context() ++ ++ init { ++ messageCollector?.let { JavacLogger.preRegister(context, it) } ++ arguments?.toList()?.let { JavacOptionsMapper.map(Options.instance(context), it) } ++ } ++ ++ private val javac = object : JavaCompiler(context) { ++ override fun parseFiles(files: Iterable?) = compilationUnits ++ } ++ private val fileManager = context[JavaFileManager::class.java] as JavacFileManager ++ ++ init { ++ fileManager.setLocation(StandardLocation.CLASS_PATH, classPathRoots) ++ outDir?.let { ++ it.mkdirs() ++ fileManager.setLocation(StandardLocation.CLASS_OUTPUT, listOf(it)) ++ } ++ } ++ ++ private val symbols = Symtab.instance(context) ++ private val trees = JavacTrees.instance(context) ++ private val elements = JavacElements.instance(context) ++ private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList() ++ private val compilationUnits: JavacList = fileObjects.map(javac::parse).toJavacList() ++ ++ private val javaClasses = compilationUnits ++ .flatMap { unit -> unit.typeDecls ++ .flatMap { JCClass(it as JCTree.JCClassDecl, trees.getPath(unit, it), this).withInnerClasses() } ++ } ++ .map { it.fqName to it } ++ .toMap() ++ ++ private val javaPackages = compilationUnits ++ .map { FqName(it.packageName.toString()) to JCPackage(it.packageName.toString(), this) } ++ .toMap()",See above,2017-04-05 13:08:45 +709,"@@ -0,0 +1,227 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.JavacClass ++import org.jetbrains.kotlin.wrappers.symbols.JavacPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.wrappers.trees.JCClass ++import org.jetbrains.kotlin.wrappers.trees.JCPackage ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.TypeElement ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class Javac(javaFiles: Collection, ++ classPathRoots: List, ++ outDir: File?, ++ private val messageCollector: MessageCollector?, ++ arguments: Array?) : Closeable { ++ ++ companion object { ++ fun getInstance(project: Project): Javac = ServiceManager.getService(project, Javac::class.java) ++ } ++ ++ val JAVA_LANG_OBJECT by lazy { findClassInSymbols(CommonClassNames.JAVA_LANG_OBJECT) } ++ ++ private val context = Context() ++ ++ init { ++ messageCollector?.let { JavacLogger.preRegister(context, it) } ++ arguments?.toList()?.let { JavacOptionsMapper.map(Options.instance(context), it) } ++ } ++ ++ private val javac = object : JavaCompiler(context) { ++ override fun parseFiles(files: Iterable?) = compilationUnits ++ } ++ private val fileManager = context[JavaFileManager::class.java] as JavacFileManager ++ ++ init { ++ fileManager.setLocation(StandardLocation.CLASS_PATH, classPathRoots) ++ outDir?.let { ++ it.mkdirs() ++ fileManager.setLocation(StandardLocation.CLASS_OUTPUT, listOf(it)) ++ } ++ } ++ ++ private val symbols = Symtab.instance(context) ++ private val trees = JavacTrees.instance(context) ++ private val elements = JavacElements.instance(context) ++ private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList() ++ private val compilationUnits: JavacList = fileObjects.map(javac::parse).toJavacList() ++ ++ private val javaClasses = compilationUnits ++ .flatMap { unit -> unit.typeDecls ++ .flatMap { JCClass(it as JCTree.JCClassDecl, trees.getPath(unit, it), this).withInnerClasses() } ++ } ++ .map { it.fqName to it } ++ .toMap() ++ ++ private val javaPackages = compilationUnits ++ .map { FqName(it.packageName.toString()) to JCPackage(it.packageName.toString(), this) } ++ .toMap() ++ ++ fun compile() = with(javac) { ++ if (errorCount() > 0) return false ++ ++ fileManager.setClassPathForCompilation() ++ messageCollector?.report(CompilerMessageSeverity.INFO, ++ ""Compiling Java sources"", ++ CompilerMessageLocation.NO_LOCATION) ++ compile(fileObjects) ++ errorCount() == 0 ++ } ++ ++ override fun close() { ++ fileManager.close() ++ javac.close() ++ } ++ ++ fun findClass(fqName: FqName, scope: GlobalSearchScope = EverythingGlobalScope()) = when { ++ scope is EverythingGlobalScope -> javaClasses[fqName] ?: findClassInSymbols(fqName.asString()) ++ scope.contains(AnyJavaSourceVirtualFile) -> javaClasses[fqName]","I don't quite understand the idea with this object. As I can see, it's used in `contains` only. Who does put it into the scope?",2017-04-05 13:18:50 +708,"@@ -0,0 +1,227 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.JavacClass ++import org.jetbrains.kotlin.wrappers.symbols.JavacPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.wrappers.trees.JCClass ++import org.jetbrains.kotlin.wrappers.trees.JCPackage ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.TypeElement ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class Javac(javaFiles: Collection, ++ classPathRoots: List, ++ outDir: File?, ++ private val messageCollector: MessageCollector?, ++ arguments: Array?) : Closeable { ++ ++ companion object { ++ fun getInstance(project: Project): Javac = ServiceManager.getService(project, Javac::class.java) ++ } ++ ++ val JAVA_LANG_OBJECT by lazy { findClassInSymbols(CommonClassNames.JAVA_LANG_OBJECT) } ++ ++ private val context = Context() ++ ++ init { ++ messageCollector?.let { JavacLogger.preRegister(context, it) } ++ arguments?.toList()?.let { JavacOptionsMapper.map(Options.instance(context), it) } ++ } ++ ++ private val javac = object : JavaCompiler(context) { ++ override fun parseFiles(files: Iterable?) = compilationUnits ++ } ++ private val fileManager = context[JavaFileManager::class.java] as JavacFileManager ++ ++ init { ++ fileManager.setLocation(StandardLocation.CLASS_PATH, classPathRoots) ++ outDir?.let { ++ it.mkdirs() ++ fileManager.setLocation(StandardLocation.CLASS_OUTPUT, listOf(it)) ++ } ++ } ++ ++ private val symbols = Symtab.instance(context) ++ private val trees = JavacTrees.instance(context) ++ private val elements = JavacElements.instance(context) ++ private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList() ++ private val compilationUnits: JavacList = fileObjects.map(javac::parse).toJavacList() ++ ++ private val javaClasses = compilationUnits ++ .flatMap { unit -> unit.typeDecls ++ .flatMap { JCClass(it as JCTree.JCClassDecl, trees.getPath(unit, it), this).withInnerClasses() } ++ } ++ .map { it.fqName to it } ++ .toMap() ++ ++ private val javaPackages = compilationUnits ++ .map { FqName(it.packageName.toString()) to JCPackage(it.packageName.toString(), this) } ++ .toMap() ++ ++ fun compile() = with(javac) { ++ if (errorCount() > 0) return false ++ ++ fileManager.setClassPathForCompilation() ++ messageCollector?.report(CompilerMessageSeverity.INFO, ++ ""Compiling Java sources"", ++ CompilerMessageLocation.NO_LOCATION) ++ compile(fileObjects) ++ errorCount() == 0 ++ } ++ ++ override fun close() { ++ fileManager.close() ++ javac.close() ++ } ++ ++ fun findClass(fqName: FqName, scope: GlobalSearchScope = EverythingGlobalScope()) = when { ++ scope is EverythingGlobalScope -> javaClasses[fqName] ?: findClassInSymbols(fqName.asString()) ++ scope.contains(AnyJavaSourceVirtualFile) -> javaClasses[fqName] ++ else -> findClassInSymbols(fqName.asString()) ?: javaClasses[fqName] ++ } ++ ++ fun findPackage(fqName: FqName, scope: GlobalSearchScope) = when { ++ scope is EverythingGlobalScope -> javaPackages[fqName] ?: findPackageInSymbols(fqName.asString()) ++ scope.contains(AnyJavaSourceVirtualFile) -> javaPackages[fqName] ++ else -> findPackageInSymbols(fqName.asString()) ?: javaPackages[fqName] ++ } ++ ++ fun findSubPackages(fqName: FqName) = symbols.packages ++ .filter { (k, _) -> k.toString().startsWith(""$fqName."") } ++ .map { JavacPackage(it.value, this) } + ++ javaPackages ++ .filter { it.key.isSubpackageOf(fqName) && it.key != fqName } ++ .map { it.value }",There is `filterValues`.,2017-04-05 13:10:49 +710,"@@ -0,0 +1,227 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.JavacClass ++import org.jetbrains.kotlin.wrappers.symbols.JavacPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.wrappers.trees.JCClass ++import org.jetbrains.kotlin.wrappers.trees.JCPackage ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.TypeElement ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class Javac(javaFiles: Collection, ++ classPathRoots: List, ++ outDir: File?, ++ private val messageCollector: MessageCollector?, ++ arguments: Array?) : Closeable { ++ ++ companion object { ++ fun getInstance(project: Project): Javac = ServiceManager.getService(project, Javac::class.java) ++ } ++ ++ val JAVA_LANG_OBJECT by lazy { findClassInSymbols(CommonClassNames.JAVA_LANG_OBJECT) } ++ ++ private val context = Context() ++ ++ init { ++ messageCollector?.let { JavacLogger.preRegister(context, it) } ++ arguments?.toList()?.let { JavacOptionsMapper.map(Options.instance(context), it) } ++ } ++ ++ private val javac = object : JavaCompiler(context) { ++ override fun parseFiles(files: Iterable?) = compilationUnits ++ } ++ private val fileManager = context[JavaFileManager::class.java] as JavacFileManager ++ ++ init { ++ fileManager.setLocation(StandardLocation.CLASS_PATH, classPathRoots) ++ outDir?.let { ++ it.mkdirs() ++ fileManager.setLocation(StandardLocation.CLASS_OUTPUT, listOf(it)) ++ } ++ } ++ ++ private val symbols = Symtab.instance(context) ++ private val trees = JavacTrees.instance(context) ++ private val elements = JavacElements.instance(context) ++ private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList() ++ private val compilationUnits: JavacList = fileObjects.map(javac::parse).toJavacList() ++ ++ private val javaClasses = compilationUnits ++ .flatMap { unit -> unit.typeDecls ++ .flatMap { JCClass(it as JCTree.JCClassDecl, trees.getPath(unit, it), this).withInnerClasses() } ++ } ++ .map { it.fqName to it } ++ .toMap() ++ ++ private val javaPackages = compilationUnits ++ .map { FqName(it.packageName.toString()) to JCPackage(it.packageName.toString(), this) } ++ .toMap() ++ ++ fun compile() = with(javac) { ++ if (errorCount() > 0) return false ++ ++ fileManager.setClassPathForCompilation() ++ messageCollector?.report(CompilerMessageSeverity.INFO, ++ ""Compiling Java sources"", ++ CompilerMessageLocation.NO_LOCATION) ++ compile(fileObjects) ++ errorCount() == 0 ++ } ++ ++ override fun close() { ++ fileManager.close() ++ javac.close() ++ } ++ ++ fun findClass(fqName: FqName, scope: GlobalSearchScope = EverythingGlobalScope()) = when { ++ scope is EverythingGlobalScope -> javaClasses[fqName] ?: findClassInSymbols(fqName.asString()) ++ scope.contains(AnyJavaSourceVirtualFile) -> javaClasses[fqName] ++ else -> findClassInSymbols(fqName.asString()) ?: javaClasses[fqName] ++ } ++ ++ fun findPackage(fqName: FqName, scope: GlobalSearchScope) = when { ++ scope is EverythingGlobalScope -> javaPackages[fqName] ?: findPackageInSymbols(fqName.asString()) ++ scope.contains(AnyJavaSourceVirtualFile) -> javaPackages[fqName] ++ else -> findPackageInSymbols(fqName.asString()) ?: javaPackages[fqName] ++ } ++ ++ fun findSubPackages(fqName: FqName) = symbols.packages ++ .filter { (k, _) -> k.toString().startsWith(""$fqName."") } ++ .map { JavacPackage(it.value, this) } + ++ javaPackages ++ .filter { it.key.isSubpackageOf(fqName) && it.key != fqName } ++ .map { it.value } ++ ++ fun findClassesFromPackage(fqName: FqName) = javaClasses.filter { it.key?.parentOrNull() == fqName } ++ .flatMap { it.value.withInnerClasses() } + ++ elements.getPackageElement(fqName.asString()) ++ ?.members() ++ ?.elements ++ ?.filterIsInstance(TypeElement::class.java) ++ ?.map { JavacClass(it, this) } ++ .orEmpty() ++ ++ fun getTreePath(tree: JCTree, compilationUnit: CompilationUnitTree): TreePath = trees.getPath(compilationUnit, tree) ++ ++ private inline fun Iterable.toJavacList() = JavacList.from(this) ++ ++ private fun findClassInSymbols(fqName: String) = elements.getTypeElement(fqName)?.let { JavacClass(it, this) } ++ ++ private fun findPackageInSymbols(fqName: String) = elements.getPackageElement(fqName)?.let { JavacPackage(it, this) } ++ ++ private fun JavacFileManager.setClassPathForCompilation() = apply { ++ setLocation(StandardLocation.CLASS_PATH, ++ getLocation(StandardLocation.CLASS_PATH) + getLocation(StandardLocation.CLASS_OUTPUT)) ++ ++ val reader = ClassReader.instance(context) ++ val names = Names.instance(context) ++ val outDirName = getLocation(StandardLocation.CLASS_OUTPUT).firstOrNull()?.path ?: """" ++ ++ list(StandardLocation.CLASS_OUTPUT, """", setOf(JavaFileObject.Kind.CLASS), true) ++ .forEach { ++ val fqName = it.name ++ .substringAfter(outDirName) ++ .substringBefore("".class"") ++ .replace(""/"", ""."") ++ .let { if (it.startsWith(""."")) it.substring(1) else it } ++ .let(names::fromString) ++ ++ symbols.classes[fqName]?.let { symbols.classes[fqName] = null } ++ val symbol = reader.enterClass(fqName, it) ++ ++ (elements.getPackageOf(symbol) as? Symbol.PackageSymbol)?.let { ++ it.members_field.enter(symbol) ++ it.flags_field = it.flags_field or Flags.EXISTS.toLong() ++ } ++ } ++ ++ } ++ ++ private fun JavaClass.withInnerClasses(): List = listOf(this) + innerClasses.flatMap { it.withInnerClasses() } ++ ++} ++ ++private object AnyJavaSourceVirtualFile : VirtualFile() { ++ override fun refresh(asynchronous: Boolean, recursive: Boolean, postRunnable: Runnable?) {} ++ ++ override fun getLength() = 0L ++ ++ override fun getFileSystem() = throw UnsupportedOperationException()","May be (if you need this object at all) it's better to provide some message like `""Should never be called""`. ",2017-04-05 13:20:04 +977,"@@ -0,0 +1,24 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.factories ++ ++import org.jetbrains.kotlin.effectsystem.structure.ESBooleanExpression ++import org.jetbrains.kotlin.effectsystem.structure.ESClause ++import org.jetbrains.kotlin.effectsystem.structure.ESEffect ++ ++fun createClause(premise: ESBooleanExpression, conclusion: ESEffect) = ESClause(premise, conclusion) ++fun createUnconditionalClause(effect: ESEffect): ESClause = ESClause(true.lift(), effect)","Why do we need this `unconditionalClause`? As far as I understand it's interpreted as ""if effect takes place then true is true"", and this statement is always true.",2017-08-15 16:24:21 +538,"@@ -0,0 +1,240 @@ ++@file:kotlin.jvm.JvmMultifileClass ++@file:kotlin.jvm.JvmName(""StringsKt"") ++@file:Suppress(""PLATFORM_CLASS_MAPPED_TO_KOTLIN"") ++ ++package kotlin.text ++ ++ ++/** ++ * Returns `true` if the contents of this string is equal to the word ""true"", ignoring case, and `false` otherwise. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toBoolean(): Boolean = java.lang.Boolean.parseBoolean(this) ++ ++/** ++ * Parses the string as a signed [Byte] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toByte(radix: Int = 10): Byte = java.lang.Byte.parseByte(this, radix) ++ ++/** ++ * Parses the string as a [Short] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toShort(radix: Int = 10): Short = java.lang.Short.parseShort(this, radix) ++ ++/** ++ * Parses the string as an [Int] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toInt(radix: Int = 10): Int = java.lang.Integer.parseInt(this, radix) ++ ++/** ++ * Parses the string as a [Long] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toLong(radix: Int = 10): Long = java.lang.Long.parseLong(this, radix) ++ ++/** ++ * Parses the string as a [Float] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toFloat(radix: Int = 10): Float = java.lang.Float.parseFloat(this)","Radix parameter seems to be unused +",2016-04-21 07:07:12 +539,"@@ -0,0 +1,240 @@ ++@file:kotlin.jvm.JvmMultifileClass ++@file:kotlin.jvm.JvmName(""StringsKt"") ++@file:Suppress(""PLATFORM_CLASS_MAPPED_TO_KOTLIN"") ++ ++package kotlin.text ++ ++ ++/** ++ * Returns `true` if the contents of this string is equal to the word ""true"", ignoring case, and `false` otherwise. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toBoolean(): Boolean = java.lang.Boolean.parseBoolean(this) ++ ++/** ++ * Parses the string as a signed [Byte] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toByte(radix: Int = 10): Byte = java.lang.Byte.parseByte(this, radix) ++ ++/** ++ * Parses the string as a [Short] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toShort(radix: Int = 10): Short = java.lang.Short.parseShort(this, radix) ++ ++/** ++ * Parses the string as an [Int] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toInt(radix: Int = 10): Int = java.lang.Integer.parseInt(this, radix) ++ ++/** ++ * Parses the string as a [Long] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toLong(radix: Int = 10): Long = java.lang.Long.parseLong(this, radix) ++ ++/** ++ * Parses the string as a [Float] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toFloat(radix: Int = 10): Float = java.lang.Float.parseFloat(this) ++ ++/** ++ * Parses the string as a [Double] number and returns the result. ++ * @throws NumberFormatException if the string is not a valid representation of a number. ++ */ ++@kotlin.internal.InlineOnly ++public inline fun String.toDouble(radix: Int = 10): Double = java.lang.Double.parseDouble(this)","Radix parameter seems to be unused +",2016-04-21 07:07:21 +791,"@@ -0,0 +1,243 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope","I think it would be nice to move parts of this class that use `com.intellij.openapi` to other compiler modules, to get rid of dependency of module `javac-wrapper` on `openapi`. This can be done in the future, I suppose.",2017-04-25 10:28:28 +776,"@@ -0,0 +1,243 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.model.JavacTypes ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.config.CompilerConfiguration ++import org.jetbrains.kotlin.config.JVMConfigurationKeys ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.wrappers.trees.TreeBasedClass ++import org.jetbrains.kotlin.wrappers.trees.TreeBasedPackage ++import org.jetbrains.kotlin.wrappers.trees.TreePathResolverCache ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.Element ++import javax.lang.model.element.TypeElement ++import javax.lang.model.type.TypeMirror ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class JavacWrapper(javaFiles: Collection,","Since you're passing `CompilerConfiguration` here, there's no need to pass `classPathRoots` and `messageCollector` separately because in production code, they can be trivially obtained from the configuration (and tests can be adapted to mimic that)",2017-04-25 07:50:20 +813,"@@ -0,0 +1,243 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.intellij.ide.highlighter.JavaFileType ++import com.intellij.openapi.components.ServiceManager ++import com.intellij.openapi.fileTypes.FileType ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.CommonClassNames ++import com.intellij.psi.search.EverythingGlobalScope ++import com.intellij.psi.search.GlobalSearchScope ++import com.sun.source.tree.CompilationUnitTree ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.api.JavacTrees ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.code.Symbol ++import com.sun.tools.javac.code.Symtab ++import com.sun.tools.javac.file.JavacFileManager ++import com.sun.tools.javac.jvm.ClassReader ++import com.sun.tools.javac.main.JavaCompiler ++import com.sun.tools.javac.model.JavacElements ++import com.sun.tools.javac.model.JavacTypes ++import com.sun.tools.javac.tree.JCTree ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Names ++import com.sun.tools.javac.util.Options ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.config.CompilerConfiguration ++import org.jetbrains.kotlin.config.JVMConfigurationKeys ++import com.sun.tools.javac.util.List as JavacList ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedClass ++import org.jetbrains.kotlin.wrappers.symbols.SymbolBasedPackage ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.isSubpackageOf ++import org.jetbrains.kotlin.name.parentOrNull ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.wrappers.trees.TreeBasedClass ++import org.jetbrains.kotlin.wrappers.trees.TreeBasedPackage ++import org.jetbrains.kotlin.wrappers.trees.TreePathResolverCache ++import java.io.Closeable ++import java.io.File ++import javax.lang.model.element.Element ++import javax.lang.model.element.TypeElement ++import javax.lang.model.type.TypeMirror ++import javax.tools.JavaFileManager ++import javax.tools.JavaFileObject ++import javax.tools.StandardLocation ++ ++class JavacWrapper(javaFiles: Collection, ++ kotlinFiles: Collection, ++ classPathRoots: List, ++ private val configuration: CompilerConfiguration, ++ private val messageCollector: MessageCollector?, ++ arguments: Array?) : Closeable { ++ ++ companion object { ++ fun getInstance(project: Project): JavacWrapper = ServiceManager.getService(project, JavacWrapper::class.java) ++ } ++ ++ val JAVA_LANG_OBJECT by lazy { findClassInSymbols(CommonClassNames.JAVA_LANG_OBJECT) } ++ ++ private val context = Context() ++ ++ init { ++ messageCollector?.let { JavacLogger.preRegister(context, it) } ++ arguments?.toList()?.let { JavacOptionsMapper.map(Options.instance(context), it) } ++ } ++ ++ private val javac = object : JavaCompiler(context) { ++ override fun parseFiles(files: Iterable?) = compilationUnits ++ } ++ private val fileManager = context[JavaFileManager::class.java] as JavacFileManager ++ ++ init { ++ fileManager.setLocation(StandardLocation.CLASS_PATH, classPathRoots) ++ } ++ ++ private val symbols = Symtab.instance(context) ++ private val trees = JavacTrees.instance(context) ++ private val elements = JavacElements.instance(context) ++ private val types = JavacTypes.instance(context) ++ private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList() ++ private val compilationUnits: JavacList = fileObjects.map(javac::parse).toJavacList() ++ ++ private val javaClasses = compilationUnits ++ .flatMap { unit -> unit.typeDecls ++ .flatMap { TreeBasedClass(it as JCTree.JCClassDecl, trees.getPath(unit, it), this).withInnerClasses() } ++ } ++ .associateBy(JavaClass::fqName) ++ ++ private val javaPackages = compilationUnits ++ .map { TreeBasedPackage(it.packageName.toString(), this) } ++ .associateBy(TreeBasedPackage::fqName) ++ ++ private val kotlinClassifiersCache = KotlinClassifiersCache(kotlinFiles, this) ++ private val treePathResolverCache = TreePathResolverCache(this) ++ ++ fun compile(outDir: File? = null) = with(javac) { ++ if (errorCount() > 0) return false ++ ++ fileManager.setClassPathForCompilation(outDir) ++ messageCollector?.report(CompilerMessageSeverity.INFO, ++ ""Compiling Java sources"") ++ compile(fileObjects) ++ errorCount() == 0 ++ } ++ ++ override fun close() { ++ fileManager.close() ++ javac.close() ++ } ++ ++ fun findClass(fqName: FqName, scope: GlobalSearchScope = EverythingGlobalScope()) = when { ++ scope is EverythingGlobalScope -> javaClasses[fqName] ?: findClassInSymbols(fqName.asString())","Using `instanceof` on `GlobalSearchScope` is very risky and should be avoided at all costs. For example, if I wrap the everything-scope twice into the not-scope: +``` +GlobalSearchScope.notScope(GlobalSearchScope.notScope( + GlobalSearchScope.allScope(project) +)) +``` +The resulting scope will be effectively the same, but your code won't work anymore because it would be another instance. + +Also, relying on specific scopes being passed here (like a scope with all .java files) is risky as well, because we might reconfigure the compiler in such a way that the compiled module is split into a different set of scopes in the near future.",2017-04-25 12:40:53 +136,"@@ -0,0 +1,25 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++public enum class ExpressionKind(val output: String) { ++ IF : ExpressionKind(""if"") ++ ELSE : ExpressionKind(""else"") ++ WHILE : ExpressionKind(""while"") ++ DOWHILE : ExpressionKind(""do...while"") ++ FOR : ExpressionKind(""for"") ++}","Storing string representation in enum is a good idea. +I think this enum shouldn't be public and is better to put it near corresponding methods in Utils.kt +",2014-03-05 16:42:00 +489,"@@ -0,0 +1,25 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.psi; ++ ++import com.intellij.psi.PsiElement; ++import org.jetbrains.annotations.Nullable; ++ ++public interface KtValVarKeywordProvider extends PsiElement {","""Provider"" is not a great name for it, I think +",2015-11-03 11:53:33 +480,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput(","Not related to changes, but why is it uppercase? +",2015-09-23 14:50:43 +479,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput( ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ stream: ByteArrayOutputStream, ++ exitCode: String) { ++ val reader = BufferedReader(StringReader(stream.toString())) ++ CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector) ++ ++ if (INTERNAL_ERROR == exitCode) { ++ reportInternalCompilerError(messageCollector) ++ } ++ } ++ ++ private fun reportInternalCompilerError(messageCollector: MessageCollector) { ++ messageCollector.report(ERROR, ""Compiler terminated with internal error"", CompilerMessageLocation.NO_LOCATION) ++ } ++ ++ private fun runCompiler( ++ compilerClassName: String, ++ arguments: CommonCompilerArguments, ++ additionalArguments: String, ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment) { ++ try { ++ messageCollector.report(INFO, ""Using kotlin-home = "" + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) ++ ++ val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments) ++ argumentsList.addAll(StringUtil.split(additionalArguments, "" ""))","Please use Kotlin's `split` +",2015-09-23 14:48:19 +478,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput( ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ stream: ByteArrayOutputStream, ++ exitCode: String) { ++ val reader = BufferedReader(StringReader(stream.toString())) ++ CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector) ++ ++ if (INTERNAL_ERROR == exitCode) { ++ reportInternalCompilerError(messageCollector) ++ } ++ } ++ ++ private fun reportInternalCompilerError(messageCollector: MessageCollector) { ++ messageCollector.report(ERROR, ""Compiler terminated with internal error"", CompilerMessageLocation.NO_LOCATION) ++ } ++ ++ private fun runCompiler( ++ compilerClassName: String, ++ arguments: CommonCompilerArguments, ++ additionalArguments: String, ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment) { ++ try { ++ messageCollector.report(INFO, ""Using kotlin-home = "" + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) ++ ++ val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments) ++ argumentsList.addAll(StringUtil.split(additionalArguments, "" "")) ++ ++ val argsArray = ArrayUtil.toStringArray(argumentsList)","`toTypedArray()` +",2015-09-23 14:48:04 +477,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput( ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ stream: ByteArrayOutputStream, ++ exitCode: String) { ++ val reader = BufferedReader(StringReader(stream.toString())) ++ CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector) ++ ++ if (INTERNAL_ERROR == exitCode) { ++ reportInternalCompilerError(messageCollector) ++ } ++ } ++ ++ private fun reportInternalCompilerError(messageCollector: MessageCollector) { ++ messageCollector.report(ERROR, ""Compiler terminated with internal error"", CompilerMessageLocation.NO_LOCATION) ++ } ++ ++ private fun runCompiler( ++ compilerClassName: String, ++ arguments: CommonCompilerArguments, ++ additionalArguments: String, ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment) { ++ try { ++ messageCollector.report(INFO, ""Using kotlin-home = "" + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) ++ ++ val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments) ++ argumentsList.addAll(StringUtil.split(additionalArguments, "" "")) ++ ++ val argsArray = ArrayUtil.toStringArray(argumentsList) ++ ++ if (!tryCompileWithDaemon(messageCollector, collector, environment, argsArray)) { ++ // otherwise fallback to in-process ++ ++ val stream = ByteArrayOutputStream() ++ val out = PrintStream(stream) ++ ++ val rc = CompilerRunnerUtil.invokeExecMethod(compilerClassName, argsArray, environment, messageCollector, out) ++ ++ // exec() returns an ExitCode object, class of which is loaded with a different class loader, ++ // so we take it's contents through reflection ++ ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc)) ++ } ++ } ++ catch (e: Throwable) { ++ MessageCollectorUtil.reportException(messageCollector, e) ++ reportInternalCompilerError(messageCollector) ++ } ++ ++ } ++ ++ private fun tryCompileWithDaemon(messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment, ++ argsArray: Array): Boolean { ++ if (isDaemonEnabled()) {","Early return would be helpful +",2015-09-23 14:47:49 +476,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput( ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ stream: ByteArrayOutputStream, ++ exitCode: String) { ++ val reader = BufferedReader(StringReader(stream.toString())) ++ CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector) ++ ++ if (INTERNAL_ERROR == exitCode) { ++ reportInternalCompilerError(messageCollector) ++ } ++ } ++ ++ private fun reportInternalCompilerError(messageCollector: MessageCollector) { ++ messageCollector.report(ERROR, ""Compiler terminated with internal error"", CompilerMessageLocation.NO_LOCATION) ++ } ++ ++ private fun runCompiler( ++ compilerClassName: String, ++ arguments: CommonCompilerArguments, ++ additionalArguments: String, ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment) { ++ try { ++ messageCollector.report(INFO, ""Using kotlin-home = "" + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) ++ ++ val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments) ++ argumentsList.addAll(StringUtil.split(additionalArguments, "" "")) ++ ++ val argsArray = ArrayUtil.toStringArray(argumentsList) ++ ++ if (!tryCompileWithDaemon(messageCollector, collector, environment, argsArray)) { ++ // otherwise fallback to in-process ++ ++ val stream = ByteArrayOutputStream() ++ val out = PrintStream(stream) ++ ++ val rc = CompilerRunnerUtil.invokeExecMethod(compilerClassName, argsArray, environment, messageCollector, out) ++ ++ // exec() returns an ExitCode object, class of which is loaded with a different class loader, ++ // so we take it's contents through reflection ++ ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc)) ++ } ++ } ++ catch (e: Throwable) { ++ MessageCollectorUtil.reportException(messageCollector, e) ++ reportInternalCompilerError(messageCollector) ++ } ++ ++ } ++ ++ private fun tryCompileWithDaemon(messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment, ++ argsArray: Array): Boolean { ++ if (isDaemonEnabled()) { ++ val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector) ++ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ ++ // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler ++ val compilerId = CompilerId.makeCompilerId(File(libPath, ""kotlin-compiler.jar"")) ++ val daemonOptions = configureDaemonOptions() ++ val daemonJVMOptions = configureDaemonJVMOptions(true) ++ ++ val daemonReportMessages = ArrayList() ++ ++ val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true) ++ ++ for (msg in daemonReportMessages) { ++ if (msg.category === DaemonReportCategory.EXCEPTION && daemon == null) { ++ messageCollector.report(CompilerMessageSeverity.INFO, ++ ""Falling back to compilation without daemon due to error: "" + msg.message, ++ CompilerMessageLocation.NO_LOCATION) ++ } ++ else { ++ messageCollector.report(CompilerMessageSeverity.INFO, msg.message, CompilerMessageLocation.NO_LOCATION) ++ } ++ } ++ ++ if (daemon != null) { ++ val compilerOut = ByteArrayOutputStream() ++ val daemonOut = ByteArrayOutputStream() ++ ++ val services = CompilationServices( ++ incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java), ++ compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java)) ++ ++ val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, services, compilerOut, daemonOut) ++ ++ ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString()) ++ BufferedReader(StringReader(daemonOut.toString())).forEachLine { ++ messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION) ++ } ++ return true ++ } ++ } ++ return false ++ } ++ ++ private fun getReturnCodeFromObject(rc: Any?): String { ++ if (rc == null) {","`when` +",2015-09-23 14:46:49 +475,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput( ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ stream: ByteArrayOutputStream, ++ exitCode: String) { ++ val reader = BufferedReader(StringReader(stream.toString())) ++ CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector) ++ ++ if (INTERNAL_ERROR == exitCode) { ++ reportInternalCompilerError(messageCollector) ++ } ++ } ++ ++ private fun reportInternalCompilerError(messageCollector: MessageCollector) { ++ messageCollector.report(ERROR, ""Compiler terminated with internal error"", CompilerMessageLocation.NO_LOCATION) ++ } ++ ++ private fun runCompiler( ++ compilerClassName: String, ++ arguments: CommonCompilerArguments, ++ additionalArguments: String, ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment) { ++ try { ++ messageCollector.report(INFO, ""Using kotlin-home = "" + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) ++ ++ val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments) ++ argumentsList.addAll(StringUtil.split(additionalArguments, "" "")) ++ ++ val argsArray = ArrayUtil.toStringArray(argumentsList) ++ ++ if (!tryCompileWithDaemon(messageCollector, collector, environment, argsArray)) { ++ // otherwise fallback to in-process ++ ++ val stream = ByteArrayOutputStream() ++ val out = PrintStream(stream) ++ ++ val rc = CompilerRunnerUtil.invokeExecMethod(compilerClassName, argsArray, environment, messageCollector, out) ++ ++ // exec() returns an ExitCode object, class of which is loaded with a different class loader, ++ // so we take it's contents through reflection ++ ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc)) ++ } ++ } ++ catch (e: Throwable) { ++ MessageCollectorUtil.reportException(messageCollector, e) ++ reportInternalCompilerError(messageCollector) ++ } ++ ++ } ++ ++ private fun tryCompileWithDaemon(messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment, ++ argsArray: Array): Boolean { ++ if (isDaemonEnabled()) { ++ val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector) ++ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ ++ // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler ++ val compilerId = CompilerId.makeCompilerId(File(libPath, ""kotlin-compiler.jar"")) ++ val daemonOptions = configureDaemonOptions() ++ val daemonJVMOptions = configureDaemonJVMOptions(true) ++ ++ val daemonReportMessages = ArrayList() ++ ++ val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true) ++ ++ for (msg in daemonReportMessages) { ++ if (msg.category === DaemonReportCategory.EXCEPTION && daemon == null) { ++ messageCollector.report(CompilerMessageSeverity.INFO, ++ ""Falling back to compilation without daemon due to error: "" + msg.message, ++ CompilerMessageLocation.NO_LOCATION) ++ } ++ else { ++ messageCollector.report(CompilerMessageSeverity.INFO, msg.message, CompilerMessageLocation.NO_LOCATION) ++ } ++ } ++ ++ if (daemon != null) { ++ val compilerOut = ByteArrayOutputStream() ++ val daemonOut = ByteArrayOutputStream() ++ ++ val services = CompilationServices( ++ incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java), ++ compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java)) ++ ++ val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, services, compilerOut, daemonOut) ++ ++ ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString()) ++ BufferedReader(StringReader(daemonOut.toString())).forEachLine { ++ messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION) ++ } ++ return true ++ } ++ } ++ return false ++ } ++ ++ private fun getReturnCodeFromObject(rc: Any?): String { ++ if (rc == null) { ++ return INTERNAL_ERROR ++ } ++ else if (ExitCode::class.java.name == rc.javaClass.name) { ++ return rc.toString() ++ } ++ else { ++ throw IllegalStateException(""Unexpected return: "" + rc) ++ } ++ } ++ ++ private fun mergeBeans(from: CommonCompilerArguments, to: T): T { ++ // TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity ++ try { ++ val copy = XmlSerializerUtil.createCopy(to) ++ ++ val fromFields = collectFieldsToCopy(from.javaClass) ++ for (fromField in fromFields) { ++ val toField = copy.javaClass.getField(fromField.name) ++ toField.set(copy, fromField.get(from)) ++ } ++ ++ return copy ++ } ++ catch (e: NoSuchFieldException) { ++ throw rethrow(e) ++ } ++ catch (e: IllegalAccessException) { ++ throw rethrow(e)","This `try`/`catch` and `rethrow`s are not needed in Kotlin +",2015-09-23 14:46:18 +473,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput( ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ stream: ByteArrayOutputStream, ++ exitCode: String) { ++ val reader = BufferedReader(StringReader(stream.toString())) ++ CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector) ++ ++ if (INTERNAL_ERROR == exitCode) { ++ reportInternalCompilerError(messageCollector) ++ } ++ } ++ ++ private fun reportInternalCompilerError(messageCollector: MessageCollector) { ++ messageCollector.report(ERROR, ""Compiler terminated with internal error"", CompilerMessageLocation.NO_LOCATION) ++ } ++ ++ private fun runCompiler( ++ compilerClassName: String, ++ arguments: CommonCompilerArguments, ++ additionalArguments: String, ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment) { ++ try { ++ messageCollector.report(INFO, ""Using kotlin-home = "" + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) ++ ++ val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments) ++ argumentsList.addAll(StringUtil.split(additionalArguments, "" "")) ++ ++ val argsArray = ArrayUtil.toStringArray(argumentsList) ++ ++ if (!tryCompileWithDaemon(messageCollector, collector, environment, argsArray)) { ++ // otherwise fallback to in-process ++ ++ val stream = ByteArrayOutputStream() ++ val out = PrintStream(stream) ++ ++ val rc = CompilerRunnerUtil.invokeExecMethod(compilerClassName, argsArray, environment, messageCollector, out) ++ ++ // exec() returns an ExitCode object, class of which is loaded with a different class loader, ++ // so we take it's contents through reflection ++ ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc)) ++ } ++ } ++ catch (e: Throwable) { ++ MessageCollectorUtil.reportException(messageCollector, e) ++ reportInternalCompilerError(messageCollector) ++ } ++ ++ } ++ ++ private fun tryCompileWithDaemon(messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment, ++ argsArray: Array): Boolean { ++ if (isDaemonEnabled()) { ++ val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector) ++ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ ++ // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler ++ val compilerId = CompilerId.makeCompilerId(File(libPath, ""kotlin-compiler.jar"")) ++ val daemonOptions = configureDaemonOptions() ++ val daemonJVMOptions = configureDaemonJVMOptions(true) ++ ++ val daemonReportMessages = ArrayList() ++ ++ val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true) ++ ++ for (msg in daemonReportMessages) { ++ if (msg.category === DaemonReportCategory.EXCEPTION && daemon == null) { ++ messageCollector.report(CompilerMessageSeverity.INFO, ++ ""Falling back to compilation without daemon due to error: "" + msg.message, ++ CompilerMessageLocation.NO_LOCATION) ++ } ++ else { ++ messageCollector.report(CompilerMessageSeverity.INFO, msg.message, CompilerMessageLocation.NO_LOCATION) ++ } ++ } ++ ++ if (daemon != null) { ++ val compilerOut = ByteArrayOutputStream() ++ val daemonOut = ByteArrayOutputStream() ++ ++ val services = CompilationServices( ++ incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java), ++ compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java)) ++ ++ val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, services, compilerOut, daemonOut) ++ ++ ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString()) ++ BufferedReader(StringReader(daemonOut.toString())).forEachLine { ++ messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION) ++ } ++ return true ++ } ++ } ++ return false ++ } ++ ++ private fun getReturnCodeFromObject(rc: Any?): String { ++ if (rc == null) { ++ return INTERNAL_ERROR ++ } ++ else if (ExitCode::class.java.name == rc.javaClass.name) { ++ return rc.toString() ++ } ++ else { ++ throw IllegalStateException(""Unexpected return: "" + rc) ++ } ++ } ++ ++ private fun mergeBeans(from: CommonCompilerArguments, to: T): T { ++ // TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity ++ try { ++ val copy = XmlSerializerUtil.createCopy(to) ++ ++ val fromFields = collectFieldsToCopy(from.javaClass) ++ for (fromField in fromFields) { ++ val toField = copy.javaClass.getField(fromField.name) ++ toField.set(copy, fromField.get(from)) ++ } ++ ++ return copy ++ } ++ catch (e: NoSuchFieldException) { ++ throw rethrow(e) ++ } ++ catch (e: IllegalAccessException) { ++ throw rethrow(e) ++ } ++ ++ } ++ ++ private fun collectFieldsToCopy(clazz: Class<*>): List { ++ val fromFields = ArrayList() ++ ++ var currentClass: Class<*>? = clazz ++ while (currentClass != null) { ++ for (field in currentClass.declaredFields) { ++ val modifiers = field.modifiers ++ if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) { ++ fromFields.add(field) ++ } ++ } ++ currentClass = currentClass.superclass ++ } ++ ++ return fromFields ++ } ++ ++ private fun setupK2JvmArguments(moduleFile: File, settings: K2JVMCompilerArguments) { ++ settings.module = moduleFile.absolutePath ++ settings.noStdlib = true ++ settings.noJdkAnnotations = true ++ settings.noJdk = true ++ } ++ ++ private fun setupK2JsArguments( ++ outputFile: File, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ settings: K2JSCompilerArguments) { ++ settings.noStdlib = true ++ settings.freeArgs = ContainerUtil.map(sourceFiles, object : Function {","Please use Kotlin's `map { ... }` +",2015-09-23 14:45:19 +474,"@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.compilerRunner ++ ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.util.ArrayUtil ++import com.intellij.util.Function ++import com.intellij.util.containers.ContainerUtil ++import com.intellij.util.xmlb.XmlSerializerUtil ++import org.jetbrains.kotlin.cli.common.ExitCode ++import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil ++import org.jetbrains.kotlin.config.CompilerSettings ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents ++import org.jetbrains.kotlin.progress.CompilationCanceledStatus ++import org.jetbrains.kotlin.rmi.CompilerId ++import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions ++import org.jetbrains.kotlin.rmi.configureDaemonOptions ++import org.jetbrains.kotlin.rmi.isDaemonEnabled ++import org.jetbrains.kotlin.rmi.kotlinr.* ++import org.jetbrains.kotlin.utils.rethrow ++import java.io.* ++import java.lang.reflect.Field ++import java.lang.reflect.Modifier ++import java.util.* ++ ++public object KotlinCompilerRunner { ++ private val K2JVM_COMPILER = ""org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"" ++ private val K2JS_COMPILER = ""org.jetbrains.kotlin.cli.js.K2JSCompiler"" ++ private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() ++ ++ public fun runK2JvmCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jvmArguments: K2JVMCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ moduleFile: File, ++ collector: OutputItemsCollector) { ++ val arguments = mergeBeans(commonArguments, k2jvmArguments) ++ setupK2JvmArguments(moduleFile, arguments) ++ ++ runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ public fun runK2JsCompiler( ++ commonArguments: CommonCompilerArguments, ++ k2jsArguments: K2JSCompilerArguments, ++ compilerSettings: CompilerSettings, ++ messageCollector: MessageCollector, ++ environment: CompilerEnvironment, ++ collector: OutputItemsCollector, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ outputFile: File) { ++ val arguments = mergeBeans(commonArguments, k2jsArguments) ++ setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) ++ ++ runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment) ++ } ++ ++ private fun ProcessCompilerOutput( ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ stream: ByteArrayOutputStream, ++ exitCode: String) { ++ val reader = BufferedReader(StringReader(stream.toString())) ++ CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector) ++ ++ if (INTERNAL_ERROR == exitCode) { ++ reportInternalCompilerError(messageCollector) ++ } ++ } ++ ++ private fun reportInternalCompilerError(messageCollector: MessageCollector) { ++ messageCollector.report(ERROR, ""Compiler terminated with internal error"", CompilerMessageLocation.NO_LOCATION) ++ } ++ ++ private fun runCompiler( ++ compilerClassName: String, ++ arguments: CommonCompilerArguments, ++ additionalArguments: String, ++ messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment) { ++ try { ++ messageCollector.report(INFO, ""Using kotlin-home = "" + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) ++ ++ val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments) ++ argumentsList.addAll(StringUtil.split(additionalArguments, "" "")) ++ ++ val argsArray = ArrayUtil.toStringArray(argumentsList) ++ ++ if (!tryCompileWithDaemon(messageCollector, collector, environment, argsArray)) { ++ // otherwise fallback to in-process ++ ++ val stream = ByteArrayOutputStream() ++ val out = PrintStream(stream) ++ ++ val rc = CompilerRunnerUtil.invokeExecMethod(compilerClassName, argsArray, environment, messageCollector, out) ++ ++ // exec() returns an ExitCode object, class of which is loaded with a different class loader, ++ // so we take it's contents through reflection ++ ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc)) ++ } ++ } ++ catch (e: Throwable) { ++ MessageCollectorUtil.reportException(messageCollector, e) ++ reportInternalCompilerError(messageCollector) ++ } ++ ++ } ++ ++ private fun tryCompileWithDaemon(messageCollector: MessageCollector, ++ collector: OutputItemsCollector, ++ environment: CompilerEnvironment, ++ argsArray: Array): Boolean { ++ if (isDaemonEnabled()) { ++ val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector) ++ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ ++ // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler ++ val compilerId = CompilerId.makeCompilerId(File(libPath, ""kotlin-compiler.jar"")) ++ val daemonOptions = configureDaemonOptions() ++ val daemonJVMOptions = configureDaemonJVMOptions(true) ++ ++ val daemonReportMessages = ArrayList() ++ ++ val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true) ++ ++ for (msg in daemonReportMessages) { ++ if (msg.category === DaemonReportCategory.EXCEPTION && daemon == null) { ++ messageCollector.report(CompilerMessageSeverity.INFO, ++ ""Falling back to compilation without daemon due to error: "" + msg.message, ++ CompilerMessageLocation.NO_LOCATION) ++ } ++ else { ++ messageCollector.report(CompilerMessageSeverity.INFO, msg.message, CompilerMessageLocation.NO_LOCATION) ++ } ++ } ++ ++ if (daemon != null) { ++ val compilerOut = ByteArrayOutputStream() ++ val daemonOut = ByteArrayOutputStream() ++ ++ val services = CompilationServices( ++ incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java), ++ compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java)) ++ ++ val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, services, compilerOut, daemonOut) ++ ++ ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString()) ++ BufferedReader(StringReader(daemonOut.toString())).forEachLine { ++ messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION) ++ } ++ return true ++ } ++ } ++ return false ++ } ++ ++ private fun getReturnCodeFromObject(rc: Any?): String { ++ if (rc == null) { ++ return INTERNAL_ERROR ++ } ++ else if (ExitCode::class.java.name == rc.javaClass.name) { ++ return rc.toString() ++ } ++ else { ++ throw IllegalStateException(""Unexpected return: "" + rc) ++ } ++ } ++ ++ private fun mergeBeans(from: CommonCompilerArguments, to: T): T { ++ // TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity ++ try { ++ val copy = XmlSerializerUtil.createCopy(to) ++ ++ val fromFields = collectFieldsToCopy(from.javaClass) ++ for (fromField in fromFields) { ++ val toField = copy.javaClass.getField(fromField.name) ++ toField.set(copy, fromField.get(from)) ++ } ++ ++ return copy ++ } ++ catch (e: NoSuchFieldException) { ++ throw rethrow(e) ++ } ++ catch (e: IllegalAccessException) { ++ throw rethrow(e) ++ } ++ ++ } ++ ++ private fun collectFieldsToCopy(clazz: Class<*>): List { ++ val fromFields = ArrayList() ++ ++ var currentClass: Class<*>? = clazz ++ while (currentClass != null) { ++ for (field in currentClass.declaredFields) { ++ val modifiers = field.modifiers ++ if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) { ++ fromFields.add(field) ++ } ++ } ++ currentClass = currentClass.superclass ++ } ++ ++ return fromFields ++ } ++ ++ private fun setupK2JvmArguments(moduleFile: File, settings: K2JVMCompilerArguments) { ++ settings.module = moduleFile.absolutePath ++ settings.noStdlib = true ++ settings.noJdkAnnotations = true ++ settings.noJdk = true ++ } ++ ++ private fun setupK2JsArguments( ++ outputFile: File, ++ sourceFiles: Collection, ++ libraryFiles: List, ++ settings: K2JSCompilerArguments) { ++ settings.noStdlib = true ++ settings.freeArgs = ContainerUtil.map(sourceFiles, object : Function { ++ override fun `fun`(file: File): String { ++ return file.path ++ } ++ }) ++ settings.outputFile = outputFile.path ++ settings.metaInfo = true ++ settings.libraryFiles = ArrayUtil.toStringArray(libraryFiles)","`toTypedArray()` +",2015-09-23 14:45:36 +357,"@@ -0,0 +1,26 @@ ++/* ++ * Copyright 2010-2015 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 kotlin.jvm ++ ++import java.lang.annotation.Retention ++import java.lang.annotation.RetentionPolicy ++ ++/** ++ * Instructs the Kotlin compiler to generate overloads for this function that substitute default parameter values.","Maybe it will be useful to document exactly what overloads are generated here? One might think that `2^n` overloads will be generated, if `n` is the number of default parameters +",2015-04-01 14:27:42 +701,"@@ -0,0 +1,26 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.descriptors.SourceFile ++import org.jetbrains.kotlin.load.java.sources.JavaSourceElement ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++ ++class JavacSourceElement(override val javaElement: JavaElement) : JavaSourceElement {",`JavacBasedSourceElement`?,2017-04-05 12:56:28 +702,"@@ -0,0 +1,26 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++ ++class JavacSourceElementFactory : JavaSourceElementFactory {",`JavacBasedSourceElementFactory`?,2017-04-05 12:58:21 +247,"@@ -0,0 +1,26 @@ ++import kotlin.test.assertEquals ++ ++fun test1() { ++ val u = when (true) { ++ true -> 42 ++ else -> 1.0 ++ } ++ ++ assertEquals(42, u) ++} ++ ++fun test2() { ++ val u = 1L.let { ++ when (it) { ++ is Long -> if (it.toLong() == 2L) it.toLong() else it * 2 // CompilationException ++ else -> it.toDouble() ++ } ++ } ++ ++ assertEquals(1L, u) ++} ++ ++fun box(): String { ++ return ""OK""","what about test1, test2 call? +",2014-09-24 13:18:33 +405,"@@ -0,0 +1,262 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() =","~~Why do we need our own isAlive implementation?~~ +My bad. `Process.isAlive` was introduced in Java 8 +",2015-08-19 22:01:03 +412,"@@ -0,0 +1,262 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator)","Will we see black console window on Windows if we start `java.exe`? Shouldn't we run `javaw.exe` instead? +",2015-08-19 22:42:40 +406,"@@ -0,0 +1,262 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false ++ ++ val stdouThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) ++ lock.write { isEchoRead = true; return@forEachLine } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ var waitMillis: Long = DAEMON_STARTUP_TIMEOUT_MS / DAEMON_STARTUP_CHECK_INTERVAL_MS ++ while (waitMillis-- > 0) { ++ Thread.sleep(DAEMON_STARTUP_CHECK_INTERVAL_MS) ++ if (!daemon.isAlive() || lock.read { isEchoRead } == true) break; ++ } ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (lock.read { isEchoRead } == false) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdouThread.isAlive)","But if it is not then the child process could hang if there are bytes were not consumed: generally it may happen if the child process is trying to write to the pipe but nobody reads it anymore and the pipe internal buffer is full +",2015-08-19 22:17:44 +407,"@@ -0,0 +1,262 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false ++ ++ val stdouThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) ++ lock.write { isEchoRead = true; return@forEachLine } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ var waitMillis: Long = DAEMON_STARTUP_TIMEOUT_MS / DAEMON_STARTUP_CHECK_INTERVAL_MS ++ while (waitMillis-- > 0) { ++ Thread.sleep(DAEMON_STARTUP_CHECK_INTERVAL_MS) ++ if (!daemon.isAlive() || lock.read { isEchoRead } == true) break; ++ } ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (lock.read { isEchoRead } == false) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdouThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ lock.write { stdouThread.stop() } ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } ++ ++ public fun connectToCompileService(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { ++ val service = connectToService(compilerId, daemonOptions, errStream) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId, errStream)) { ++ errStream.println(""[daemon client] found the suitable daemon"") ++ return service ++ } ++ errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.asParams.joinToString("" "")) ++ if (!autostart) return null; ++ errStream.println(""[daemon client] shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way","pidfile, some kind of ping, shutdown port? +",2015-08-19 22:24:10 +408,"@@ -0,0 +1,262 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false ++ ++ val stdouThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) ++ lock.write { isEchoRead = true; return@forEachLine } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ var waitMillis: Long = DAEMON_STARTUP_TIMEOUT_MS / DAEMON_STARTUP_CHECK_INTERVAL_MS ++ while (waitMillis-- > 0) { ++ Thread.sleep(DAEMON_STARTUP_CHECK_INTERVAL_MS) ++ if (!daemon.isAlive() || lock.read { isEchoRead } == true) break; ++ } ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (lock.read { isEchoRead } == false) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdouThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ lock.write { stdouThread.stop() } ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } ++ ++ public fun connectToCompileService(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { ++ val service = connectToService(compilerId, daemonOptions, errStream) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId, errStream)) { ++ errStream.println(""[daemon client] found the suitable daemon"") ++ return service ++ } ++ errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.asParams.joinToString("" "")) ++ if (!autostart) return null; ++ errStream.println(""[daemon client] shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ } ++ else { ++ if (!autostart) return null; ++ else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ } ++ ++ startDaemon(compilerId, daemonLaunchingOptions, daemonOptions, errStream) ++ errStream.println(""[daemon client] daemon started, trying to connect"") ++ return connectToService(compilerId, daemonOptions, errStream) ++ } ++ ++ public fun shutdownCompileService(): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonLaunchingOptions(), DaemonOptions(), System.out, autostart = false, checkId = false) ++ ?.shutdown() ++ } ++ ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ val cacheServers = hashMapOf() ++ try { ++ caches.forEach { cacheServers.put( it.getKey(), RemoteIncrementalCacheServer( it.getValue())) } ++ val res = compiler.remoteIncrementalCompile(args, cacheServers, outStrm, CompileService.OutputFormat.XML) ++ return res ++ } ++ finally { ++ cacheServers.forEach { it.getValue().disconnect() } ++ outStrm.disconnect() ++ } ++ } ++ ++ public fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null ++ ++ public fun configureDaemonLaunchingOptions(opts: DaemonLaunchingOptions) { ++ System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let { ++ // TODO: find better way to pass and parse jvm options for daemon ++ opts.jvmParams = it.split(""##"") ++ } ++ } ++ ++ data class ClientOptions( ++ public var stop: Boolean = false ++ ) :CmdlineParams { ++ override val asParams: Iterable ++ get() = ++ if (stop) listOf(""stop"") else listOf()","listOf() -> emptyList() +",2015-08-19 22:25:55 +409,"@@ -0,0 +1,262 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false ++ ++ val stdouThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) ++ lock.write { isEchoRead = true; return@forEachLine } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ var waitMillis: Long = DAEMON_STARTUP_TIMEOUT_MS / DAEMON_STARTUP_CHECK_INTERVAL_MS ++ while (waitMillis-- > 0) { ++ Thread.sleep(DAEMON_STARTUP_CHECK_INTERVAL_MS) ++ if (!daemon.isAlive() || lock.read { isEchoRead } == true) break; ++ } ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (lock.read { isEchoRead } == false) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdouThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ lock.write { stdouThread.stop() } ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } ++ ++ public fun connectToCompileService(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { ++ val service = connectToService(compilerId, daemonOptions, errStream) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId, errStream)) { ++ errStream.println(""[daemon client] found the suitable daemon"") ++ return service ++ } ++ errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.asParams.joinToString("" "")) ++ if (!autostart) return null; ++ errStream.println(""[daemon client] shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ } ++ else { ++ if (!autostart) return null; ++ else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ } ++ ++ startDaemon(compilerId, daemonLaunchingOptions, daemonOptions, errStream) ++ errStream.println(""[daemon client] daemon started, trying to connect"") ++ return connectToService(compilerId, daemonOptions, errStream) ++ } ++ ++ public fun shutdownCompileService(): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonLaunchingOptions(), DaemonOptions(), System.out, autostart = false, checkId = false) ++ ?.shutdown() ++ } ++ ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ val cacheServers = hashMapOf() ++ try { ++ caches.forEach { cacheServers.put( it.getKey(), RemoteIncrementalCacheServer( it.getValue())) } ++ val res = compiler.remoteIncrementalCompile(args, cacheServers, outStrm, CompileService.OutputFormat.XML) ++ return res ++ } ++ finally { ++ cacheServers.forEach { it.getValue().disconnect() } ++ outStrm.disconnect() ++ } ++ } ++ ++ public fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null ++ ++ public fun configureDaemonLaunchingOptions(opts: DaemonLaunchingOptions) { ++ System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let { ++ // TODO: find better way to pass and parse jvm options for daemon ++ opts.jvmParams = it.split(""##"") ++ } ++ } ++ ++ data class ClientOptions( ++ public var stop: Boolean = false ++ ) :CmdlineParams { ++ override val asParams: Iterable ++ get() = ++ if (stop) listOf(""stop"") else listOf() ++ ++ override val parsers: List> ++ get() = listOf( BoolPropParser(this, ::stop)) ++ } ++ ++ platformStatic public fun main(vararg args: String) { ++ val compilerId = CompilerId() ++ val daemonOptions = DaemonOptions() ++ val daemonLaunchingOptions = DaemonLaunchingOptions() ++ val clientOptions = ClientOptions() ++ val filteredArgs = args.asIterable().propParseFilter(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions) ++ ++ if (!clientOptions.stop) { ++ if (compilerId.compilerClasspath.none()) { ++ // attempt to find compiler to use ++ println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") ++ System.getProperty(""java.class.path"") ++ ?.split(File.pathSeparator) ++ ?.map { File(it).parent } ++ ?.distinct() ++ ?.map { ++ it?.walk() ++ ?.firstOrNull { it.getName().equals(COMPILER_JAR_NAME, ignoreCase = true) } ++ } ++ ?.filterNotNull() ++ ?.firstOrNull() ++ ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } ++ } ++ if (compilerId.compilerClasspath.none()) ++ throw IllegalArgumentException(""Cannot find compiler jar"") ++ else ++ println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) ++ ++ compilerId.updateDigest() ++ } ++ ++ connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, System.out, autostart = !clientOptions.stop, checkId = !clientOptions.stop)?.let { ++ when { ++ clientOptions.stop -> { ++ println(""Shutdown the daemon"") ++ it.shutdown() ++ println(""Daemon shut down successfully"") ++ } ++ else -> { ++ println(""Executing daemon compilation with args: "" + filteredArgs.joinToString("" "")) ++ val outStrm = RemoteOutputStreamServer(System.out) ++ try { ++ val memBefore = it.getUsedMemory() / 1024 ++ val startTime = System.nanoTime() ++ val res = it.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN) ++ val endTime = System.nanoTime()","We can use kotlin's `measureTimeMillis` or `measureTimeNano`: http://kotlinlang.org/api/latest/jvm/stdlib/kotlin.util/index.html +",2015-08-19 22:28:46 +465,"@@ -0,0 +1,263 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import kotlin.concurrent.thread ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { ++ val javaw = File(it, ""javaw.exe"") ++ if (javaw.exists()) javaw ++ else File(it, ""java"") ++ } ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable.absolutePath, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonJVMOptions.mappers.flatMap { it.toArgs(""-"") } + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + ++ compilerId.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ var isEchoRead = Semaphore(1) ++ isEchoRead.acquire() ++ ++ val stdoutThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) { ++ isEchoRead.release() ++ return@forEachLine ++ } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ val succeeded = isEchoRead.tryAcquire(DAEMON_STARTUP_TIMEOUT_MS, TimeUnit.MILLISECONDS) ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (!succeeded) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdoutThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ stdoutThread.stop() ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } ++ ++ public fun connectToCompileService(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { ++ val service = connectToService(compilerId, daemonOptions, errStream) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId, errStream)) { ++ errStream.println(""[daemon client] found the suitable daemon"") ++ return service ++ } ++ errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.mappers.flatMap { it.toArgs("""") }.joinToString("" "")) ++ if (!autostart) return null; ++ errStream.println(""[daemon client] shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ } ++ else { ++ if (!autostart) return null; ++ else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ } ++ ++ startDaemon(compilerId, daemonJVMOptions, daemonOptions, errStream) ++ errStream.println(""[daemon client] daemon started, trying to connect"") ++ return connectToService(compilerId, daemonOptions, errStream) ++ } ++ ++ public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, System.out, autostart = false, checkId = false) ++ ?.shutdown() ++ } ++ ++ public fun shutdownCompileService(): Unit { ++ shutdownCompileService(DaemonOptions()) ++ } ++ ++ public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ try { ++ return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN) ++ } ++ finally { ++ outStrm.disconnect() ++ } ++ } ++ ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ val cacheServers = hashMapOf() ++ try { ++ caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer( it.getValue()) }) ++ return compiler.remoteIncrementalCompile(args, cacheServers, outStrm, CompileService.OutputFormat.XML) ++ } ++ finally { ++ cacheServers.forEach { it.getValue().disconnect() } ++ outStrm.disconnect() ++ } ++ } ++ ++ data class ClientOptions( ++ public var stop: Boolean = false ++ ) : OptionsGroup { ++ override val mappers: List> ++ get() = listOf( BoolPropMapper(this, ::stop)) ++ } ++ ++ jvmStatic public fun main(vararg args: String) { ++ val compilerId = CompilerId() ++ val daemonOptions = DaemonOptions() ++ val daemonLaunchingOptions = DaemonJVMOptions() ++ val clientOptions = ClientOptions() ++ val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) ++ ++ if (!clientOptions.stop) { ++ if (compilerId.compilerClasspath.none()) { ++ // attempt to find compiler to use ++ println(""compiler wasn't explicitly specified, attempt to find appropriate jar"")","Why are you printing this & other information to stdout, not stderr? +",2015-09-01 07:29:59 +964,"@@ -0,0 +1,27 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.structure ++ ++interface ESEffect { ++ /** ++ * Returns: ++ * - true, when presence of `this`-effect necessary implies presence of `other`-effect ++ * - false, when presence of `this`-effect necessary implies absence of `other`-effect ++ * - null, when presence of `this`-effect doesn't implies neither presence nor absence of `other`-effect ++ */ ++ fun isImplies(other: ESEffect): Boolean?",It's matter of taste but I'd use here some enum with three elements,2017-08-15 15:35:58 +430,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1","Try to run optimize imports and reformat +",2015-08-24 12:14:46 +428,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient {","Looks like it should be object +",2015-08-24 12:02:18 +432,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L","private? +",2015-08-24 12:22:32 +431,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? {","we prefer to first declare a public API +",2015-08-24 12:22:20 +433,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running","minor: I'd inline `connectToDaemon` +",2015-08-24 12:23:10 +429,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?:","Why ClassCastException is not enough here? +",2015-08-24 12:08:31 +434,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null)","We prefer to use braces in `if` except one-line ifs: `if (cond) return/break/continue` +",2015-08-24 12:50:33 +435,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { ++ val javaw = File(it, ""javaw.exe"") ++ if (javaw.exists()) javaw ++ else File(it, ""java"") ++ } ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable.absolutePath, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.extractors.flatMap { it.extract(""-"") } + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.extractors.flatMap { it.extract(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + ++ compilerId.extractors.flatMap { it.extract(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ var isEchoRead = Semaphore(1) ++ isEchoRead.acquire() ++ ++ val stdoutThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) { ++ isEchoRead.release() ++ return@forEachLine ++ } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ val succeeded = isEchoRead.tryAcquire(DAEMON_STARTUP_TIMEOUT_MS, TimeUnit.MILLISECONDS) ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (!succeeded) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else","braces +",2015-08-24 12:53:32 +457,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { ++ val javaw = File(it, ""javaw.exe"") ++ if (javaw.exists()) javaw ++ else File(it, ""java"") ++ } ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable.absolutePath, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.extractors.flatMap { it.extract(""-"") } + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.extractors.flatMap { it.extract(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + ++ compilerId.extractors.flatMap { it.extract(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ var isEchoRead = Semaphore(1) ++ isEchoRead.acquire() ++ ++ val stdoutThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) { ++ isEchoRead.release() ++ return@forEachLine ++ } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ val succeeded = isEchoRead.tryAcquire(DAEMON_STARTUP_TIMEOUT_MS, TimeUnit.MILLISECONDS) ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (!succeeded) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdoutThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ stdoutThread.stop() ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) &&","why we skip empty parameters? +",2015-08-26 20:31:57 +458,"@@ -0,0 +1,271 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.Semaphore ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++import kotlin.reflect.KProperty1 ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { ++ val javaw = File(it, ""javaw.exe"") ++ if (javaw.exists()) javaw ++ else File(it, ""java"") ++ } ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable.absolutePath, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.extractors.flatMap { it.extract(""-"") } + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.extractors.flatMap { it.extract(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + ++ compilerId.extractors.flatMap { it.extract(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ var isEchoRead = Semaphore(1) ++ isEchoRead.acquire() ++ ++ val stdoutThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) { ++ isEchoRead.release() ++ return@forEachLine ++ } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ val succeeded = isEchoRead.tryAcquire(DAEMON_STARTUP_TIMEOUT_MS, TimeUnit.MILLISECONDS) ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (!succeeded) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdoutThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ stdoutThread.stop() ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) &&","`containsAll` +",2015-08-26 20:32:41 +436,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf)","i'd just add default value for `name` to primary constructor +",2015-08-25 12:24:13 +439,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull()","we can get list with string which ends with ""null"" and `filterNotNull` is unnecessary here +",2015-08-25 13:34:27 +446,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable {","I think we need better name for this function +",2015-08-25 18:00:38 +444,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param ->","I think it'll be simpler if rewrite with `while` +",2015-08-25 17:06:36 +443,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true }","replace `;` with `\n` +",2015-08-25 16:31:24 +445,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true","please don't mix blocks with and without braces +",2015-08-25 17:07:21 +448,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable {","minor: I don't like `Cmdline` +",2015-08-25 18:15:36 +455,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List>","I think these properties should not be part of public api +",2015-08-26 17:24:49 +447,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable =","what is cs? +",2015-08-25 18:03:11 +456,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """",","I don't like public vars and public constructor in inheritors of CmdlineParams +",2015-08-26 18:59:17 +441,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"),","I'd extract `{ it.isEmpty() }` to constant +",2015-08-25 15:21:39 +442,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true),","i'd extract `{ it }` or use `identity()` from `core/util.runtime/src/org/jetbrains/kotlin/utils/functions.kt` +",2015-08-25 15:23:25 +440,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true), ++ PropParser(this, ::maxPermSize, listOf(""XX:MaxPermSize""), { it }, allowMergedArg = true),","Should `allowMergedArg` be false here? +",2015-08-25 15:20:54 +449,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true), ++ PropParser(this, ::maxPermSize, listOf(""XX:MaxPermSize""), { it }, allowMergedArg = true), ++ PropParser(this, ::reservedCodeCacheSize, listOf(""XX:ReservedCodeCacheSize""), { it }, allowMergedArg = true)) ++ // otherJvmParams is missing here deliberately, it is used explicitly as a restParser param to filterSetProps ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */,","I'd toggle case of `s` or drop `auto` prefix +",2015-08-25 19:22:38 +450,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true), ++ PropParser(this, ::maxPermSize, listOf(""XX:MaxPermSize""), { it }, allowMergedArg = true), ++ PropParser(this, ::reservedCodeCacheSize, listOf(""XX:ReservedCodeCacheSize""), { it }, allowMergedArg = true)) ++ // otherJvmParams is missing here deliberately, it is used explicitly as a restParser param to filterSetProps ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */, ++ public var autoshutdownIdleSeconds: Int = 0 /* 0 means unchecked */, ++ public var startEcho: String = COMPILER_SERVICE_RMI_NAME ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::port), ++ PropExtractor(this, ::autoshutdownMemoryThreshold, skipIf = { it == 0L }), ++ PropExtractor(this, ::autoshutdownIdleSeconds, skipIf = { it == 0 }), ++ PropExtractor(this, ::startEcho)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::port, { it.toInt()}), ++ PropParser(this, ::autoshutdownMemoryThreshold, { it.toLong()}), ++ PropParser(this, ::autoshutdownIdleSeconds, { it.toInt()}), ++ PropParser(this, ::startEcho, { it.trim('""') })) ++} ++ ++ ++val COMPILER_ID_DIGEST = ""MD5""","private? +",2015-08-25 19:27:21 +451,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true), ++ PropParser(this, ::maxPermSize, listOf(""XX:MaxPermSize""), { it }, allowMergedArg = true), ++ PropParser(this, ::reservedCodeCacheSize, listOf(""XX:ReservedCodeCacheSize""), { it }, allowMergedArg = true)) ++ // otherJvmParams is missing here deliberately, it is used explicitly as a restParser param to filterSetProps ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */, ++ public var autoshutdownIdleSeconds: Int = 0 /* 0 means unchecked */, ++ public var startEcho: String = COMPILER_SERVICE_RMI_NAME ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::port), ++ PropExtractor(this, ::autoshutdownMemoryThreshold, skipIf = { it == 0L }), ++ PropExtractor(this, ::autoshutdownIdleSeconds, skipIf = { it == 0 }), ++ PropExtractor(this, ::startEcho)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::port, { it.toInt()}), ++ PropParser(this, ::autoshutdownMemoryThreshold, { it.toLong()}), ++ PropParser(this, ::autoshutdownIdleSeconds, { it.toInt()}), ++ PropParser(this, ::startEcho, { it.trim('""') })) ++} ++ ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++ ++fun updateSingleFileDigest(file: File, md: MessageDigest) {","private? +",2015-08-26 13:42:48 +452,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true), ++ PropParser(this, ::maxPermSize, listOf(""XX:MaxPermSize""), { it }, allowMergedArg = true), ++ PropParser(this, ::reservedCodeCacheSize, listOf(""XX:ReservedCodeCacheSize""), { it }, allowMergedArg = true)) ++ // otherJvmParams is missing here deliberately, it is used explicitly as a restParser param to filterSetProps ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */, ++ public var autoshutdownIdleSeconds: Int = 0 /* 0 means unchecked */, ++ public var startEcho: String = COMPILER_SERVICE_RMI_NAME ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::port), ++ PropExtractor(this, ::autoshutdownMemoryThreshold, skipIf = { it == 0L }), ++ PropExtractor(this, ::autoshutdownIdleSeconds, skipIf = { it == 0 }), ++ PropExtractor(this, ::startEcho)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::port, { it.toInt()}), ++ PropParser(this, ::autoshutdownMemoryThreshold, { it.toLong()}), ++ PropParser(this, ::autoshutdownIdleSeconds, { it.toInt()}), ++ PropParser(this, ::startEcho, { it.trim('""') })) ++} ++ ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++ ++fun updateSingleFileDigest(file: File, md: MessageDigest) { ++ DigestInputStream(file.inputStream(), md).use { ++ val buf = ByteArray(1024) ++ while (it.read(buf) != -1) { } ++ it.close() ++ } ++} ++ ++fun updateForAllClasses(dir: File, md: MessageDigest) { ++ dir.walk().forEach { updateEntryDigest(it, md) } ++} ++ ++fun updateEntryDigest(entry: File, md: MessageDigest) { ++ when { ++ entry.isDirectory ++ -> updateForAllClasses(entry, md) ++ entry.isFile && ++ (entry.getName().endsWith("".class"", ignoreCase = true) ||","`getName()` can be replaces with `name` +",2015-08-26 14:42:30 +453,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true), ++ PropParser(this, ::maxPermSize, listOf(""XX:MaxPermSize""), { it }, allowMergedArg = true), ++ PropParser(this, ::reservedCodeCacheSize, listOf(""XX:ReservedCodeCacheSize""), { it }, allowMergedArg = true)) ++ // otherJvmParams is missing here deliberately, it is used explicitly as a restParser param to filterSetProps ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */, ++ public var autoshutdownIdleSeconds: Int = 0 /* 0 means unchecked */, ++ public var startEcho: String = COMPILER_SERVICE_RMI_NAME ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::port), ++ PropExtractor(this, ::autoshutdownMemoryThreshold, skipIf = { it == 0L }), ++ PropExtractor(this, ::autoshutdownIdleSeconds, skipIf = { it == 0 }), ++ PropExtractor(this, ::startEcho)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::port, { it.toInt()}), ++ PropParser(this, ::autoshutdownMemoryThreshold, { it.toLong()}), ++ PropParser(this, ::autoshutdownIdleSeconds, { it.toInt()}), ++ PropParser(this, ::startEcho, { it.trim('""') })) ++} ++ ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++ ++fun updateSingleFileDigest(file: File, md: MessageDigest) { ++ DigestInputStream(file.inputStream(), md).use { ++ val buf = ByteArray(1024) ++ while (it.read(buf) != -1) { } ++ it.close() ++ } ++} ++ ++fun updateForAllClasses(dir: File, md: MessageDigest) { ++ dir.walk().forEach { updateEntryDigest(it, md) } ++} ++ ++fun updateEntryDigest(entry: File, md: MessageDigest) { ++ when { ++ entry.isDirectory ++ -> updateForAllClasses(entry, md) ++ entry.isFile && ++ (entry.getName().endsWith("".class"", ignoreCase = true) || ++ entry.getName().endsWith("".jar"", ignoreCase = true)) ++ -> updateSingleFileDigest(entry, md) ++ // else skip ++ } ++} ++ ++fun Iterable.getFilesClasspathDigest(): String { ++ val md = MessageDigest.getInstance(COMPILER_ID_DIGEST) ++ this.forEach { updateEntryDigest(it, md) } ++ return md.digest().joinToString("""", transform = { ""%02x"".format(it) }) ++} ++ ++fun Iterable.getClasspathDigest(): String = map { File(it) }.getFilesClasspathDigest() ++ ++ ++public data class CompilerId( ++ public var compilerClasspath: List = listOf(), ++ public var compilerDigest: String = """", ++ public var compilerVersion: String = """" ++ // TODO: checksum ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::compilerClasspath, convert = { it.joinToString(File.pathSeparator) }), ++ PropExtractor(this, ::compilerDigest), ++ PropExtractor(this, ::compilerVersion, skipIf = { it.isEmpty() })) ++ ++ override val parsers: List> ++ get() = ++ listOf( PropParser(this, ::compilerClasspath, { it.trim('""').split(File.pathSeparator)}), ++ PropParser(this, ::compilerDigest, { it.trim('""') }), ++ PropParser(this, ::compilerVersion, { it.trim('""') })) ++ ++ public fun updateDigest() { ++ compilerDigest = compilerClasspath.getClasspathDigest() ++ } ++ ++ companion object { ++ public platformStatic fun makeCompilerId(vararg paths: File): CompilerId = makeCompilerId(paths.asIterable())","`platformStatic` deprecated now +",2015-08-26 16:33:29 +454,"@@ -0,0 +1,272 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.platform.platformStatic ++import kotlin.reflect.KMutableProperty1 ++import kotlin.reflect.KProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++ ++ ++open class PropExtractor>(val dest: C, ++ val prop: P, ++ val name: String, ++ val convert: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeWithDelimiter: String? = null) ++{ ++ constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++ open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++ } ++} ++ ++class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++ : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++ override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++} ++ ++ ++open class PropParser>(val dest: C, ++ val prop: P, alternativeNames: List, ++ val parse: (s: String) -> V, ++ val allowMergedArg: Boolean = false) { ++ val names = listOf(prop.name) + alternativeNames ++ constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++ fun apply(s: String) = prop.set(dest, parse(s)) ++} ++ ++class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++ ++class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++ ++fun Iterable.filterSetProps(parsers: List>, prefix: String, restParser: RestPropParser<*,*>? = null) : Iterable { ++ var currentParser: PropParser<*,*,*>? = null ++ var matchingOption = """" ++ val res = filter { param -> ++ if (currentParser == null) { ++ val parser = parsers.find { it.names.any { name -> ++ if (param.startsWith(prefix + name)) { matchingOption = prefix + name; true } ++ else false } } ++ if (parser != null) { ++ val optionLength = matchingOption.length() ++ when { ++ parser is BoolPropParser<*,*> -> ++ if (param.length() > optionLength) throw IllegalArgumentException(""Invalid switch option '$param', expecting $matchingOption without arguments"") ++ else parser.apply("""") ++ param.length() > optionLength -> ++ if (param[optionLength] != '=') { ++ if (parser.allowMergedArg) parser.apply(param.substring(optionLength)) ++ else throw IllegalArgumentException(""Invalid option syntax '$param', expecting $matchingOption[= ]"") ++ } ++ else parser.apply(param.substring(optionLength + 1)) ++ else -> currentParser = parser ++ } ++ false ++ } ++ else if (restParser != null && param.startsWith(prefix)) { ++ restParser.add(param.removePrefix(prefix)) ++ false ++ } ++ else true ++ } ++ else { ++ currentParser!!.apply(param) ++ currentParser = null ++ false ++ } ++ } ++ if (currentParser != null) throw IllegalArgumentException(""Expecting argument for the option $matchingOption"") ++ return res ++} ++ ++// TODO: find out how to create more generic variant using first constructor ++//fun C.propsToParams() { ++// val kc = C::class ++// kc.constructors.first(). ++//} ++ ++ ++ ++public interface CmdlineParams : Serializable { ++ public val extractors: List> ++ public val parsers: List> ++} ++ ++public fun Iterable.filterSetProps(vararg cs: CmdlineParams, prefix: String) : Iterable = ++ filterSetProps(cs.flatMap { it.parsers }, prefix) ++ ++ ++public data class DaemonLaunchingOptions( ++ public var maxMemory: String = """", ++ public var maxPermSize: String = """", ++ public var reservedCodeCacheSize: String = """", ++ public var otherJvmParams: MutableCollection = arrayListOf() ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::maxMemory, ""Xmx"", skipIf = { it.isEmpty() }, mergeWithDelimiter = """"), ++ PropExtractor(this, ::maxPermSize, ""XX:MaxPermSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ PropExtractor(this, ::reservedCodeCacheSize, ""XX:ReservedCodeCacheSize"", skipIf = { it.isEmpty() }, mergeWithDelimiter = ""=""), ++ RestPropExtractor(this, ::otherJvmParams)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::maxMemory, listOf(""Xmx""), { it }, allowMergedArg = true), ++ PropParser(this, ::maxPermSize, listOf(""XX:MaxPermSize""), { it }, allowMergedArg = true), ++ PropParser(this, ::reservedCodeCacheSize, listOf(""XX:ReservedCodeCacheSize""), { it }, allowMergedArg = true)) ++ // otherJvmParams is missing here deliberately, it is used explicitly as a restParser param to filterSetProps ++} ++ ++public data class DaemonOptions( ++ public var port: Int = COMPILE_DAEMON_DEFAULT_PORT, ++ public var autoshutdownMemoryThreshold: Long = 0 /* 0 means unchecked */, ++ public var autoshutdownIdleSeconds: Int = 0 /* 0 means unchecked */, ++ public var startEcho: String = COMPILER_SERVICE_RMI_NAME ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::port), ++ PropExtractor(this, ::autoshutdownMemoryThreshold, skipIf = { it == 0L }), ++ PropExtractor(this, ::autoshutdownIdleSeconds, skipIf = { it == 0 }), ++ PropExtractor(this, ::startEcho)) ++ ++ override val parsers: List> ++ get() = listOf( PropParser(this, ::port, { it.toInt()}), ++ PropParser(this, ::autoshutdownMemoryThreshold, { it.toLong()}), ++ PropParser(this, ::autoshutdownIdleSeconds, { it.toInt()}), ++ PropParser(this, ::startEcho, { it.trim('""') })) ++} ++ ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++ ++fun updateSingleFileDigest(file: File, md: MessageDigest) { ++ DigestInputStream(file.inputStream(), md).use { ++ val buf = ByteArray(1024) ++ while (it.read(buf) != -1) { } ++ it.close() ++ } ++} ++ ++fun updateForAllClasses(dir: File, md: MessageDigest) { ++ dir.walk().forEach { updateEntryDigest(it, md) } ++} ++ ++fun updateEntryDigest(entry: File, md: MessageDigest) { ++ when { ++ entry.isDirectory ++ -> updateForAllClasses(entry, md) ++ entry.isFile && ++ (entry.getName().endsWith("".class"", ignoreCase = true) || ++ entry.getName().endsWith("".jar"", ignoreCase = true)) ++ -> updateSingleFileDigest(entry, md) ++ // else skip ++ } ++} ++ ++fun Iterable.getFilesClasspathDigest(): String { ++ val md = MessageDigest.getInstance(COMPILER_ID_DIGEST) ++ this.forEach { updateEntryDigest(it, md) } ++ return md.digest().joinToString("""", transform = { ""%02x"".format(it) }) ++} ++ ++fun Iterable.getClasspathDigest(): String = map { File(it) }.getFilesClasspathDigest() ++ ++ ++public data class CompilerId( ++ public var compilerClasspath: List = listOf(), ++ public var compilerDigest: String = """", ++ public var compilerVersion: String = """" ++ // TODO: checksum ++) : CmdlineParams { ++ ++ override val extractors: List> ++ get() = listOf( PropExtractor(this, ::compilerClasspath, convert = { it.joinToString(File.pathSeparator) }), ++ PropExtractor(this, ::compilerDigest), ++ PropExtractor(this, ::compilerVersion, skipIf = { it.isEmpty() })) ++ ++ override val parsers: List> ++ get() = ++ listOf( PropParser(this, ::compilerClasspath, { it.trim('""').split(File.pathSeparator)}), ++ PropParser(this, ::compilerDigest, { it.trim('""') }), ++ PropParser(this, ::compilerVersion, { it.trim('""') })) ++ ++ public fun updateDigest() { ++ compilerDigest = compilerClasspath.getClasspathDigest() ++ } ++ ++ companion object { ++ public platformStatic fun makeCompilerId(vararg paths: File): CompilerId = makeCompilerId(paths.asIterable()) ++ ++ public platformStatic fun makeCompilerId(paths: Iterable): CompilerId =","it has only one usage +",2015-08-26 16:37:19 +414,"@@ -0,0 +1,276 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false","Would be simpler to use an AtomicBoolean here. Or better yet, a semaphore, in which case you won't need a wait loop. +",2015-08-20 13:16:24 +413,"@@ -0,0 +1,276 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false ++ ++ val stdouThread =","typo: stdoutThread +",2015-08-20 13:14:33 +415,"@@ -0,0 +1,276 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false ++ ++ val stdouThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) ++ lock.write { isEchoRead = true; return@forEachLine } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ var waitMillis: Long = DAEMON_STARTUP_TIMEOUT_MS / DAEMON_STARTUP_CHECK_INTERVAL_MS ++ while (waitMillis-- > 0) { ++ Thread.sleep(DAEMON_STARTUP_CHECK_INTERVAL_MS) ++ if (!daemon.isAlive() || lock.read { isEchoRead } == true) break; ++ } ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (lock.read { isEchoRead } == false) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdouThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ lock.write { stdouThread.stop() } ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } ++ ++ public fun connectToCompileService(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { ++ val service = connectToService(compilerId, daemonOptions, errStream) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId, errStream)) { ++ errStream.println(""[daemon client] found the suitable daemon"") ++ return service ++ } ++ errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.asParams.joinToString("" "")) ++ if (!autostart) return null; ++ errStream.println(""[daemon client] shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ } ++ else { ++ if (!autostart) return null; ++ else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ } ++ ++ startDaemon(compilerId, daemonLaunchingOptions, daemonOptions, errStream) ++ errStream.println(""[daemon client] daemon started, trying to connect"") ++ return connectToService(compilerId, daemonOptions, errStream) ++ } ++ ++ public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonLaunchingOptions(), daemonOptions, System.out, autostart = false, checkId = false) ++ ?.shutdown() ++ } ++ ++ public fun shutdownCompileService(): Unit { ++ shutdownCompileService(DaemonOptions()) ++ } ++ ++ public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ try { ++ return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN) ++ } ++ finally { ++ outStrm.disconnect() ++ } ++ } ++ ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ val cacheServers = hashMapOf() ++ try { ++ caches.forEach { cacheServers.put( it.getKey(), RemoteIncrementalCacheServer( it.getValue())) }","`mapValues()` +",2015-08-20 13:31:40 +416,"@@ -0,0 +1,276 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache ++import org.jetbrains.kotlin.rmi.* ++import java.io.File ++import java.io.OutputStream ++import java.io.PrintStream ++import java.rmi.ConnectException ++import java.rmi.Remote ++import java.rmi.registry.LocateRegistry ++import java.util.concurrent.TimeUnit ++import java.util.concurrent.locks.ReentrantReadWriteLock ++import kotlin.concurrent.read ++import kotlin.concurrent.thread ++import kotlin.concurrent.write ++import kotlin.platform.platformStatic ++ ++fun Process.isAlive() = ++ try { ++ this.exitValue() ++ false ++ } ++ catch (e: IllegalThreadStateException) { ++ true ++ } ++ ++public class KotlinCompilerClient { ++ ++ companion object { ++ ++ val DAEMON_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_STARTUP_CHECK_INTERVAL_MS = 100L ++ ++ private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ ++ val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running ++ return compilerObj as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ } ++ ++ private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { ++ try { ++ val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon ++ errStream.println(""[daemon client] daemon not found"") ++ } ++ catch (e: ConnectException) { ++ errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below ++ } ++ return null ++ } ++ ++ ++ private fun startDaemon(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { ++ val javaExecutable = listOf(System.getProperty(""java.home""), ""bin"", ""java"").joinToString(File.separator) ++ // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs ++ val args = listOf(javaExecutable, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonLaunchingOptions.jvmParams + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.asParams + ++ compilerId.asParams ++ errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() ++ ++ val lock = ReentrantReadWriteLock() ++ var isEchoRead = false ++ ++ val stdouThread = ++ thread { ++ daemon.getInputStream() ++ .reader() ++ .forEachLine { ++ if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) ++ lock.write { isEchoRead = true; return@forEachLine } ++ errStream.println(""[daemon] "" + it) ++ } ++ } ++ try { ++ // trying to wait for process ++ if (daemonOptions.startEcho.isNotEmpty()) { ++ errStream.println(""[daemon client] waiting for daemon to respond"") ++ var waitMillis: Long = DAEMON_STARTUP_TIMEOUT_MS / DAEMON_STARTUP_CHECK_INTERVAL_MS ++ while (waitMillis-- > 0) { ++ Thread.sleep(DAEMON_STARTUP_CHECK_INTERVAL_MS) ++ if (!daemon.isAlive() || lock.read { isEchoRead } == true) break; ++ } ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (lock.read { isEchoRead } == false) ++ throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") ++ } ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdouThread.isAlive) ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ lock.write { stdouThread.stop() } ++ } ++ } ++ ++ public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { ++ val remoteId = compiler.getCompilerId() ++ errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) ++ errStream.println(""[daemon client] localId = "" + localId.toString()) ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } ++ ++ public fun connectToCompileService(compilerId: CompilerId, daemonLaunchingOptions: DaemonLaunchingOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { ++ val service = connectToService(compilerId, daemonOptions, errStream) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId, errStream)) { ++ errStream.println(""[daemon client] found the suitable daemon"") ++ return service ++ } ++ errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.asParams.joinToString("" "")) ++ if (!autostart) return null; ++ errStream.println(""[daemon client] shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ } ++ else { ++ if (!autostart) return null; ++ else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ } ++ ++ startDaemon(compilerId, daemonLaunchingOptions, daemonOptions, errStream) ++ errStream.println(""[daemon client] daemon started, trying to connect"") ++ return connectToService(compilerId, daemonOptions, errStream) ++ } ++ ++ public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonLaunchingOptions(), daemonOptions, System.out, autostart = false, checkId = false) ++ ?.shutdown() ++ } ++ ++ public fun shutdownCompileService(): Unit { ++ shutdownCompileService(DaemonOptions()) ++ } ++ ++ public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ try { ++ return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN) ++ } ++ finally { ++ outStrm.disconnect() ++ } ++ } ++ ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ val cacheServers = hashMapOf() ++ try { ++ caches.forEach { cacheServers.put( it.getKey(), RemoteIncrementalCacheServer( it.getValue())) } ++ return compiler.remoteIncrementalCompile(args, cacheServers, outStrm, CompileService.OutputFormat.XML) ++ } ++ finally { ++ cacheServers.forEach { it.getValue().disconnect() } ++ outStrm.disconnect() ++ } ++ } ++ ++ public fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null ++ ++ public fun configureDaemonLaunchingOptions(opts: DaemonLaunchingOptions) { ++ System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let { ++ // TODO: find better way to pass and parse jvm options for daemon ++ opts.jvmParams = it.split(""##"") ++ } ++ } ++ ++ data class ClientOptions( ++ public var stop: Boolean = false ++ ) :CmdlineParams { ++ override val asParams: Iterable ++ get() = ++ if (stop) listOf(""stop"") else listOf() ++ ++ override val parsers: List> ++ get() = listOf( BoolPropParser(this, ::stop)) ++ } ++ ++ platformStatic public fun main(vararg args: String) { ++ val compilerId = CompilerId() ++ val daemonOptions = DaemonOptions() ++ val daemonLaunchingOptions = DaemonLaunchingOptions() ++ val clientOptions = ClientOptions() ++ val filteredArgs = args.asIterable().propParseFilter(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions) ++ ++ if (!clientOptions.stop) { ++ if (compilerId.compilerClasspath.none()) { ++ // attempt to find compiler to use ++ println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") ++ System.getProperty(""java.class.path"") ++ ?.split(File.pathSeparator) ++ ?.map { File(it).parent } ++ ?.distinct() ++ ?.map { ++ it?.walk() ++ ?.firstOrNull { it.getName().equals(COMPILER_JAR_NAME, ignoreCase = true) } ++ } ++ ?.filterNotNull() ++ ?.firstOrNull() ++ ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } ++ } ++ if (compilerId.compilerClasspath.none()) ++ throw IllegalArgumentException(""Cannot find compiler jar"") ++ else ++ println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) ++ ++ compilerId.updateDigest() ++ } ++ ++ connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, System.out, autostart = !clientOptions.stop, checkId = !clientOptions.stop)?.let { ++ when { ++ clientOptions.stop -> { ++ println(""Shutdown the daemon"") ++ it.shutdown() ++ println(""Daemon shut down successfully"") ++ } ++ else -> { ++ println(""Executing daemon compilation with args: "" + filteredArgs.joinToString("" "")) ++ val outStrm = RemoteOutputStreamServer(System.out) ++ try { ++ val memBefore = it.getUsedMemory() / 1024 ++ val startTime = System.nanoTime() ++ val res = it.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN) ++ val endTime = System.nanoTime() ++ println(""Compilation result code: $res"") ++ val memAfter = it.getUsedMemory() / 1024 ++ println(""Compilation time: "" + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + "" ms"") ++ println(""Used memory $memAfter (${""%+d"".format(memAfter - memBefore)} kb)"") ++ } ++ finally { ++ outStrm.disconnect() ++ } ++ } ++ } ++ } ++ ?: if (clientOptions.stop) println(""No daemon found to shut down"")","I think that such dangling `?:` are fairly hard to understand. +",2015-08-20 13:32:55 +610,"@@ -0,0 +1,278 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.caches ++ ++import com.intellij.openapi.projectRoots.Sdk ++import com.intellij.psi.PsiField ++import com.intellij.psi.PsiMethod ++import com.intellij.psi.PsiModifier ++import com.intellij.psi.search.GlobalSearchScope ++import com.intellij.psi.search.PsiShortNamesCache ++import com.sun.tools.javac.util.Convert.shortName ++import junit.framework.TestCase ++import org.jetbrains.kotlin.asJava.elements.KtLightField ++import org.jetbrains.kotlin.asJava.elements.KtLightMethod ++import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName ++import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil ++import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase ++import org.jetbrains.kotlin.idea.test.PluginTestCaseBase ++import org.jetbrains.kotlin.load.java.JvmAbi ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.KtProperty ++import org.jetbrains.kotlin.test.KotlinTestUtils ++ ++ ++/**","Please remove this comment +",2016-09-19 15:25:37 +671,"@@ -0,0 +1,278 @@ ++package kotlin.collections ++ ++/** ++ * Represents a source of elements with a [keyOf] function, which can be applied to each element to get its key. ++ * ++ * A [Grouping] structure serves as an intermediate step in group-and-fold operations: ++ * they group elements by their keys and then fold each group with some aggregating operation. ++ * ++ * It is created by attaching `keySelector: (T) -> K` function to a source of elements. ++ * To get an instance of [Grouping] use one of `groupingBy` extension functions: ++ * - [Iterable.groupingBy] ++ * - [Sequence.groupingBy] ++ * - [Array.groupingBy] ++ * - [CharSequence.groupingBy] ++ * ++ * For the list of group-and-fold operations available, see the [extension functions](#extension-functions) for `Grouping`. ++ */ ++@SinceKotlin(""1.1"") ++public interface Grouping { ++ /** Returns an [Iterator] which iterates through the elements of the source. */ ++ fun elementIterator(): Iterator","@{18f15b45-4413-42a3-82e7-d057983d1e65,Ilya Gorbunov} `sourceIterator()` or just `source()` ? Need to be documented: whether it creates iterator every time or keep the same instance. If the behaviour is undefined we have to notice it here.",2016-12-29 12:11:45 +672,"@@ -0,0 +1,278 @@ ++package kotlin.collections ++ ++/** ++ * Represents a source of elements with a [keyOf] function, which can be applied to each element to get its key. ++ * ++ * A [Grouping] structure serves as an intermediate step in group-and-fold operations: ++ * they group elements by their keys and then fold each group with some aggregating operation. ++ * ++ * It is created by attaching `keySelector: (T) -> K` function to a source of elements. ++ * To get an instance of [Grouping] use one of `groupingBy` extension functions: ++ * - [Iterable.groupingBy] ++ * - [Sequence.groupingBy] ++ * - [Array.groupingBy] ++ * - [CharSequence.groupingBy] ++ * ++ * For the list of group-and-fold operations available, see the [extension functions](#extension-functions) for `Grouping`. ++ */ ++@SinceKotlin(""1.1"") ++public interface Grouping { ++ /** Returns an [Iterator] which iterates through the elements of the source. */ ++ fun elementIterator(): Iterator ++ /** Extracts the key of an [element]. */ ++ fun keyOf(element: T): K ++} ++ ++/** ++ * Groups elements from the [Grouping] source by key and aggregates elements of each group with the specified [operation]. ++ * ++ * The key for each element is provided by the [Grouping.keyOf] function. ++ * ++ * @param operation function is invoked on each element with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `value`: the current value of the accumulator of a group, can be `null` if it's first `element` encountered in the group; ++ * - `element`: the element from the source being aggregated; ++ * - `first`: indicates whether it's first `element` encountered in the group. ++ * ++ * @return a [Map] associating the key of each group with the result of aggregation of the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun Grouping.aggregate( ++ operation: (key: K, value: R?, element: T, first: Boolean) -> R ++): Map { ++ val result = mutableMapOf()",Why don't we use `aggregateTo` instead?,2016-12-29 12:15:55 +673,"@@ -0,0 +1,278 @@ ++package kotlin.collections ++ ++/** ++ * Represents a source of elements with a [keyOf] function, which can be applied to each element to get its key. ++ * ++ * A [Grouping] structure serves as an intermediate step in group-and-fold operations: ++ * they group elements by their keys and then fold each group with some aggregating operation. ++ * ++ * It is created by attaching `keySelector: (T) -> K` function to a source of elements. ++ * To get an instance of [Grouping] use one of `groupingBy` extension functions: ++ * - [Iterable.groupingBy] ++ * - [Sequence.groupingBy] ++ * - [Array.groupingBy] ++ * - [CharSequence.groupingBy] ++ * ++ * For the list of group-and-fold operations available, see the [extension functions](#extension-functions) for `Grouping`. ++ */ ++@SinceKotlin(""1.1"") ++public interface Grouping { ++ /** Returns an [Iterator] which iterates through the elements of the source. */ ++ fun elementIterator(): Iterator ++ /** Extracts the key of an [element]. */ ++ fun keyOf(element: T): K ++} ++ ++/** ++ * Groups elements from the [Grouping] source by key and aggregates elements of each group with the specified [operation]. ++ * ++ * The key for each element is provided by the [Grouping.keyOf] function. ++ * ++ * @param operation function is invoked on each element with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `value`: the current value of the accumulator of a group, can be `null` if it's first `element` encountered in the group; ++ * - `element`: the element from the source being aggregated; ++ * - `first`: indicates whether it's first `element` encountered in the group. ++ * ++ * @return a [Map] associating the key of each group with the result of aggregation of the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun Grouping.aggregate( ++ operation: (key: K, value: R?, element: T, first: Boolean) -> R ++): Map { ++ val result = mutableMapOf() ++ for (e in this.elementIterator()) { ++ val key = keyOf(e) ++ val value = result[key] ++ result[key] = operation(key, value, e, value == null && !result.containsKey(key)) ++ } ++ return result ++} ++ ++/** ++ * Groups elements from the [Grouping] source by key and aggregates elements of each group with the specified [operation] ++ * to the given [destination] map. ++ * ++ * The key for each element is provided by the [Grouping.keyOf] function. ++ * ++ * @param operation a function that is invoked on each element with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `accumulator`: the current value of the accumulator of the group, can be `null` if it's first `element` encountered in the group; ++ * - `element`: the element from the source being aggregated; ++ * - `first`: indicates whether it's first `element` encountered in the group. ++ * ++ * If the [destination] map already has a value corresponding to some key, ++ * then the elements being aggregated for that key are never considered as `first`. ++ * ++ * @return the [destination] map associating the key of each group with the result of aggregation of the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun > Grouping.aggregateTo( ++ destination: M, ++ operation: (key: K, accumulator: R?, element: T, first: Boolean) -> R","`value` vs `accumulator`, `v` vs `acc`",2016-12-29 12:16:41 +674,"@@ -0,0 +1,278 @@ ++package kotlin.collections ++ ++/** ++ * Represents a source of elements with a [keyOf] function, which can be applied to each element to get its key. ++ * ++ * A [Grouping] structure serves as an intermediate step in group-and-fold operations: ++ * they group elements by their keys and then fold each group with some aggregating operation. ++ * ++ * It is created by attaching `keySelector: (T) -> K` function to a source of elements. ++ * To get an instance of [Grouping] use one of `groupingBy` extension functions: ++ * - [Iterable.groupingBy] ++ * - [Sequence.groupingBy] ++ * - [Array.groupingBy] ++ * - [CharSequence.groupingBy] ++ * ++ * For the list of group-and-fold operations available, see the [extension functions](#extension-functions) for `Grouping`. ++ */ ++@SinceKotlin(""1.1"") ++public interface Grouping { ++ /** Returns an [Iterator] which iterates through the elements of the source. */ ++ fun elementIterator(): Iterator ++ /** Extracts the key of an [element]. */ ++ fun keyOf(element: T): K ++} ++ ++/** ++ * Groups elements from the [Grouping] source by key and aggregates elements of each group with the specified [operation]. ++ * ++ * The key for each element is provided by the [Grouping.keyOf] function. ++ * ++ * @param operation function is invoked on each element with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `value`: the current value of the accumulator of a group, can be `null` if it's first `element` encountered in the group; ++ * - `element`: the element from the source being aggregated; ++ * - `first`: indicates whether it's first `element` encountered in the group. ++ * ++ * @return a [Map] associating the key of each group with the result of aggregation of the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun Grouping.aggregate( ++ operation: (key: K, value: R?, element: T, first: Boolean) -> R ++): Map { ++ val result = mutableMapOf() ++ for (e in this.elementIterator()) { ++ val key = keyOf(e) ++ val value = result[key] ++ result[key] = operation(key, value, e, value == null && !result.containsKey(key)) ++ } ++ return result ++} ++ ++/** ++ * Groups elements from the [Grouping] source by key and aggregates elements of each group with the specified [operation] ++ * to the given [destination] map. ++ * ++ * The key for each element is provided by the [Grouping.keyOf] function. ++ * ++ * @param operation a function that is invoked on each element with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `accumulator`: the current value of the accumulator of the group, can be `null` if it's first `element` encountered in the group; ++ * - `element`: the element from the source being aggregated; ++ * - `first`: indicates whether it's first `element` encountered in the group. ++ * ++ * If the [destination] map already has a value corresponding to some key, ++ * then the elements being aggregated for that key are never considered as `first`. ++ * ++ * @return the [destination] map associating the key of each group with the result of aggregation of the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun > Grouping.aggregateTo( ++ destination: M, ++ operation: (key: K, accumulator: R?, element: T, first: Boolean) -> R ++): M { ++ for (e in this.elementIterator()) { ++ val key = keyOf(e) ++ val acc = destination[key] ++ destination[key] = operation(key, acc, e, acc == null && !destination.containsKey(key)) ++ } ++ return destination ++} ++ ++/** ++ * Groups elements from the [Grouping] source by key and accumulates elements of each group with the specified [operation] ++ * starting with an initial value of accumulator provided by the [initialValueSelector] function. ++ * ++ * @param initialValueSelector a function that provides an initial value of accumulator for an each group. ++ * It's invoked with parameters: ++ * - `key`: the key of a group; ++ * - `element`: the first element being encountered in that group. ++ * ++ * @param operation a function that is invoked on each element with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `accumulator`: the current value of the accumulator of the group; ++ * - `element`: the element from the source being accumulated. ++ * ++ * @return a [Map] associating the key of each group with the result of accumulating the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun Grouping.fold( ++ initialValueSelector: (key: K, element: T) -> R, ++ operation: (key: K, accumulator: R, element: T) -> R ++): Map = ++ aggregate { key, value, e, first -> operation(key, if (first) initialValueSelector(key, e) else value as R, e) } ++ ++/** ++ * Groups elements from the [Grouping] source by key and accumulates elements of each group with the specified [operation] ++ * starting with an initial value of accumulator provided by the [initialValueSelector] function ++ * to the given [destination] map. ++ * ++ * @param initialValueSelector a function that provides an initial value of accumulator for an each group. ++ * It's invoked with parameters: ++ * - `key`: the key of a group; ++ * - `element`: the first element being encountered in that group. ++ * ++ * If the [destination] map already has a value corresponding to some key, that value is used as an initial value of ++ * the accumulator for that group and the [initialValueSelector] function is not called for that group. ++ * ++ * @param operation a function that is invoked on each element with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `accumulator`: the current value of the accumulator of the group; ++ * - `element`: the element from the source being accumulated. ++ * ++ * @return the [destination] map associating the key of each group with the result of accumulating the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun > Grouping.foldTo( ++ destination: M, ++ initialValueSelector: (key: K, element: T) -> R, ++ operation: (key: K, accumulator: R, element: T) -> R ++): M = ++ aggregateTo(destination) { key, value, e, first -> operation(key, if (first) initialValueSelector(key, e) else value as R, e) } ++ ++ ++/** ++ * Groups elements from the [Grouping] source by key and accumulates elements of each group with the specified [operation] ++ * starting with the [initialValue]. ++ * ++ * @param operation a function that is invoked on each element with the following parameters: ++ * - `accumulator`: the current value of the accumulator of the group; ++ * - `element`: the element from the source being accumulated. ++ * ++ * @return a [Map] associating the key of each group with the result of accumulating the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun Grouping.fold( ++ initialValue: R, ++ operation: (accumulator: R, element: T) -> R ++): Map = ++ aggregate { k, v, e, first -> operation(if (first) initialValue else v as R, e) } ++ ++/** ++ * Groups elements from the [Grouping] source by key and accumulates elements of each group with the specified [operation] ++ * starting with the [initialValue] to the given [destination] map. ++ * ++ * If the [destination] map already has a value corresponding to the key of some group, ++ * that value is used as an initial value of the accumulator for that group. ++ * ++ * @param operation a function that is invoked on each element with the following parameters: ++ * - `accumulator`: the current value of the accumulator of the group; ++ * - `element`: the element from the source being accumulated. ++ * ++ * @return the [destination] map associating the key of each group with the result of accumulating the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun > Grouping.foldTo( ++ destination: M, ++ initialValue: R, ++ operation: (accumulator: R, element: T) -> R ++): M = ++ aggregateTo(destination) { k, v, e, first -> operation(if (first) initialValue else v as R, e) } ++ ++ ++/** ++ * Groups elements from the [Grouping] source by key and accumulates elements of each group with the specified [operation] ++ * starting the first element in that group. ++ * ++ * @param operation a function that is invoked on each subsequent element of the group with the following parameters: ++ * - `key`: the key of a group this element belongs to; ++ * - `accumulator`: the current value of the accumulator of the group; ++ * - `element`: the element from the source being accumulated. ++ * ++ * @return a [Map] associating the key of each group with the result of accumulating the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun Grouping.reduce( ++ operation: (key: K, accumulator: S, element: T) -> S ++): Map = ++ aggregate { key, value, e, first -> ++ if (first) e else operation(key, value as S, e) ++ } ++ ++/** ++ * Groups elements from the [Grouping] source by key and accumulates elements of each group with the specified [operation] ++ * starting the first element in that group to the given [destination] map. ++ * ++ * If the [destination] map already has a value corresponding to the key of some group, ++ * that value is used as an initial value of the accumulator for that group and the first element of that group is also ++ * subjected to the [operation]. ++ ++ * @param operation a function that is invoked on each subsequent element of the group with the following parameters: ++ * - `accumulator`: the current value of the accumulator of the group; ++ * - `element`: the element from the source being folded; ++ * ++ * @return the [destination] map associating the key of each group with the result of accumulating the group elements. ++ */ ++@SinceKotlin(""1.1"") ++public inline fun > Grouping.reduceTo( ++ destination: M, ++ operation: (key: K, accumulator: S, element: T) -> S ++): M = ++ aggregateTo(destination) { key, value, e, first -> ++ if (first) e else operation(key, value as S, e) ++ } ++ ++ ++/** ++ * Groups elements from the [Grouping] source by key and counts elements in each group. ++ * ++ * @return a [Map] associating the key of each group with the count of element in the group. ++ */ ++@SinceKotlin(""1.1"") ++@JvmVersion ++public fun Grouping.eachCount(): Map = ++ // fold(0) { acc, e -> acc + 1 } optimized for boxing ++ fold( ++ initialValueSelector = { k, e -> kotlin.jvm.internal.Ref.IntRef() }, ++ operation = { k, acc, e -> acc.apply { element += 1 } }) ++ .mapValues { it.value.element } ++ ++/** ++ * Groups elements from the [Grouping] source by key and counts elements in each group to the given [destination] map. ++ * ++ * @return the [destination] map associating the key of each group with the count of element in the group. ++ */ ++@SinceKotlin(""1.1"") ++public fun > Grouping.eachCountTo(destination: M): M = ++ foldTo(destination, 0) { acc, e -> acc + 1 } ++ ++/** ++ * Groups elements from the [Grouping] source by key and sums values provided by the [valueSelector] function for elements in each group. ++ * ++ * @return a [Map] associating the key of each group with the count of element in the group. ++ */ ++@SinceKotlin(""1.1"") ++@JvmVersion ++public inline fun Grouping.eachSumOf(valueSelector: (T) -> Int): Map = ++ // fold(0) { acc, e -> acc + valueSelector(e)} optimized for boxing ++ fold( ++ initialValueSelector = { k, e -> kotlin.jvm.internal.Ref.IntRef() }, ++ operation = { k, acc, e -> acc.apply { element += valueSelector(e) } }) ++ .mapValues { it.value.element }",as we already use internal API hack we could do even more: we can create replace `IntRef` to `Int` inplace and then do unchecked cast.,2016-12-29 12:23:10 +698,"@@ -0,0 +1,28 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.descriptors.PropertyDescriptor ++import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluator ++import org.jetbrains.kotlin.load.java.structure.JavaField ++ ++class JavacJavaPropertyInitializerEvaluator : JavaPropertyInitializerEvaluator {",There is already `JavaPropertyInitializerEvaluator.DO_NOTHING` with the same functionality,2017-04-05 12:49:39 +677,"@@ -0,0 +1,282 @@ ++package kotlin.collections ++ ++/** ++ * Represents a source of elements with a [keyOf] function, which can be applied to each element to get its key. ++ * ++ * A [Grouping] structure serves as an intermediate step in group-and-fold operations: ++ * they group elements by their keys and then fold each group with some aggregating operation. ++ * ++ * It is created by attaching `keySelector: (T) -> K` function to a source of elements. ++ * To get an instance of [Grouping] use one of `groupingBy` extension functions:","|`line 32`| +|---| +""a group"" -> ""the group"" here and below",2017-01-02 17:11:16 +678,"@@ -0,0 +1,282 @@ ++package kotlin.collections ++ ++/** ++ * Represents a source of elements with a [keyOf] function, which can be applied to each element to get its key. ++ * ++ * A [Grouping] structure serves as an intermediate step in group-and-fold operations: ++ * they group elements by their keys and then fold each group with some aggregating operation. ++ * ++ * It is created by attaching `keySelector: (T) -> K` function to a source of elements. ++ * To get an instance of [Grouping] use one of `groupingBy` extension functions: ++ * - [Iterable.groupingBy] ++ * - [Sequence.groupingBy]","|`line 61`| +|---| +Any chance for some `@sample`'s?",2017-01-02 17:15:42 +842,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) {",Why not simply `at.getNonStrictParentOfType`()?,2017-05-08 12:25:55 +843,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) { ++ KtTokens.REGULAR_STRING_PART, KtTokens.ESCAPE_SEQUENCE, KtTokens.LONG_TEMPLATE_ENTRY_START, KtTokens.SHORT_TEMPLATE_ENTRY_START -> at.parent.parent as? KtStringTemplateExpression ++ KtTokens.CLOSING_QUOTE -> if (offset == at.startOffset) at.parent as? KtStringTemplateExpression else null ++ else -> null ++ ++ } ++} ++ ++ ++//Copied from StringLiteralCopyPasteProcessor to avoid erroneous inheritance ++private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArray, text: String): Int { ++ val fragmentCount = startOffsets.size ++ assert(fragmentCount > 0) ++ var totalLength = fragmentCount - 1 // number of line breaks inserted between fragments ++ for (i in 0..fragmentCount - 1) { ++ totalLength += endOffsets[i] - startOffsets[i] ++ } ++ if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { ++ return (text.length + 1) / fragmentCount - 1 ++ } ++ else { ++ return -1 ++ } ++} ++ ++class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor { ++ override fun preprocessOnCopy(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray, text: String): String? { ++ if (file !is KtFile){ ++ return null ++ } ++ val buffer = StringBuilder() ++ var changed = false ++ val fileText = file.text ++ val deducedBlockSelectionWidth = deduceBlockSelectionWidth(startOffsets, endOffsets, text) ++ ++ for (i in startOffsets.indices) { ++ if (i > 0) { ++ buffer.append('\n') // LF is added for block selection ++ } ++ ++ val fileRange = TextRange(startOffsets[i], endOffsets[i]) ++ ++ var givenTextOffset = fileRange.startOffset ++ while (givenTextOffset < fileRange.endOffset) { ++ val element: PsiElement? = file.findElementAt(givenTextOffset) ++ if (element == null) { ++ buffer.append(fileText.substring(givenTextOffset, fileRange.endOffset)) ++ break ++ } ++ val elTp = element.node.elementType ++ if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && !fileRange.contains(element.findContainingTemplate().range)) { ++ val tpEntry = element.parent as KtEscapeStringTemplateEntry ++ changed = true ++ buffer.append(tpEntry.unescapedValue) ++ givenTextOffset = element.endOffset ++ } ++ else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ //Process inner templates without escaping ++ val tpEntry = element.parent ++ val inter = fileRange.intersection(tpEntry.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ else { ++ val inter = fileRange.intersection(element.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ ++ } ++ val blockSelectionPadding = deducedBlockSelectionWidth - fileRange.length ++ for (j in 0..blockSelectionPadding - 1) { ++ buffer.append(' ') ++ } ++ ++ } ++ ++ return if (changed) buffer.toString() else null ++ } ++ ++ override fun preprocessOnPaste(project: Project, file: PsiFile, editor: Editor, text: String, rawText: RawText?): String { ++ if (file !is KtFile){ ++ return text ++ } ++ PsiDocumentManager.getInstance(project).commitDocument(editor.document) ++ val selectionModel = editor.selectionModel ++ val beginTp = file.getTemplateIfAtLiteral(selectionModel.selectionStart) ?: return text ++ val endTp = file.getTemplateIfAtLiteral(selectionModel.selectionEnd) ?: return text ++ if (beginTp.isSingleQuoted() != endTp.isSingleQuoted()) { ++ return text ++ } ++ ++ ++ return if (beginTp.isSingleQuoted()) { ++ TemplateTokenizer(text).map { ++ when (it) { ++ is LiteralChunk -> StringUtil.escaper(true, ""\$\"""").`fun`(it.text)","I think that it's better to create a single `StringBuilder` to hold the entire preprocessed contents, and to use the overload of `escapeStringCharacters` that takes a `StringBuilder` as a parameter.",2017-05-08 12:39:49 +844,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) { ++ KtTokens.REGULAR_STRING_PART, KtTokens.ESCAPE_SEQUENCE, KtTokens.LONG_TEMPLATE_ENTRY_START, KtTokens.SHORT_TEMPLATE_ENTRY_START -> at.parent.parent as? KtStringTemplateExpression ++ KtTokens.CLOSING_QUOTE -> if (offset == at.startOffset) at.parent as? KtStringTemplateExpression else null ++ else -> null ++ ++ } ++} ++ ++ ++//Copied from StringLiteralCopyPasteProcessor to avoid erroneous inheritance ++private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArray, text: String): Int { ++ val fragmentCount = startOffsets.size ++ assert(fragmentCount > 0) ++ var totalLength = fragmentCount - 1 // number of line breaks inserted between fragments ++ for (i in 0..fragmentCount - 1) { ++ totalLength += endOffsets[i] - startOffsets[i] ++ } ++ if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { ++ return (text.length + 1) / fragmentCount - 1 ++ } ++ else { ++ return -1 ++ } ++} ++ ++class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor { ++ override fun preprocessOnCopy(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray, text: String): String? { ++ if (file !is KtFile){ ++ return null ++ } ++ val buffer = StringBuilder() ++ var changed = false ++ val fileText = file.text ++ val deducedBlockSelectionWidth = deduceBlockSelectionWidth(startOffsets, endOffsets, text) ++ ++ for (i in startOffsets.indices) { ++ if (i > 0) { ++ buffer.append('\n') // LF is added for block selection ++ } ++ ++ val fileRange = TextRange(startOffsets[i], endOffsets[i]) ++ ++ var givenTextOffset = fileRange.startOffset ++ while (givenTextOffset < fileRange.endOffset) { ++ val element: PsiElement? = file.findElementAt(givenTextOffset) ++ if (element == null) { ++ buffer.append(fileText.substring(givenTextOffset, fileRange.endOffset)) ++ break ++ } ++ val elTp = element.node.elementType ++ if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && !fileRange.contains(element.findContainingTemplate().range)) { ++ val tpEntry = element.parent as KtEscapeStringTemplateEntry ++ changed = true ++ buffer.append(tpEntry.unescapedValue) ++ givenTextOffset = element.endOffset ++ } ++ else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ //Process inner templates without escaping ++ val tpEntry = element.parent ++ val inter = fileRange.intersection(tpEntry.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ else { ++ val inter = fileRange.intersection(element.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ ++ } ++ val blockSelectionPadding = deducedBlockSelectionWidth - fileRange.length ++ for (j in 0..blockSelectionPadding - 1) { ++ buffer.append(' ') ++ } ++ ++ } ++ ++ return if (changed) buffer.toString() else null ++ } ++ ++ override fun preprocessOnPaste(project: Project, file: PsiFile, editor: Editor, text: String, rawText: RawText?): String { ++ if (file !is KtFile){ ++ return text ++ } ++ PsiDocumentManager.getInstance(project).commitDocument(editor.document) ++ val selectionModel = editor.selectionModel ++ val beginTp = file.getTemplateIfAtLiteral(selectionModel.selectionStart) ?: return text ++ val endTp = file.getTemplateIfAtLiteral(selectionModel.selectionEnd) ?: return text ++ if (beginTp.isSingleQuoted() != endTp.isSingleQuoted()) { ++ return text ++ } ++ ++ ++ return if (beginTp.isSingleQuoted()) { ++ TemplateTokenizer(text).map { ++ when (it) { ++ is LiteralChunk -> StringUtil.escaper(true, ""\$\"""").`fun`(it.text) ++ is EntryChunk -> it.text ++ is NewLineChunk -> ""\\n\""+\n \"""" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ else { ++ val tripleQuoteRe = Regex(""[\""]{3,}"") ++ TemplateTokenizer(text).map { chunk -> ++ when (chunk) { ++ is LiteralChunk -> chunk.text.replace(""\$"", ""\${'$'}"").let { escapedDollar -> ++ tripleQuoteRe.replace(escapedDollar) { ""\""\"""" + ""\${'\""'}"".repeat(it.value.count() - 2) } ++ } ++ ++ is EntryChunk -> chunk.text ++ is NewLineChunk -> ""\n"" ++ ++ } ++ }.joinToString(separator = """") ++ } ++",Please reformat the files to remove unnecessary blank lines.,2017-05-08 12:41:33 +845,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) { ++ KtTokens.REGULAR_STRING_PART, KtTokens.ESCAPE_SEQUENCE, KtTokens.LONG_TEMPLATE_ENTRY_START, KtTokens.SHORT_TEMPLATE_ENTRY_START -> at.parent.parent as? KtStringTemplateExpression ++ KtTokens.CLOSING_QUOTE -> if (offset == at.startOffset) at.parent as? KtStringTemplateExpression else null ++ else -> null ++ ++ } ++} ++ ++ ++//Copied from StringLiteralCopyPasteProcessor to avoid erroneous inheritance ++private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArray, text: String): Int { ++ val fragmentCount = startOffsets.size ++ assert(fragmentCount > 0) ++ var totalLength = fragmentCount - 1 // number of line breaks inserted between fragments ++ for (i in 0..fragmentCount - 1) { ++ totalLength += endOffsets[i] - startOffsets[i] ++ } ++ if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { ++ return (text.length + 1) / fragmentCount - 1 ++ } ++ else { ++ return -1 ++ } ++} ++ ++class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor { ++ override fun preprocessOnCopy(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray, text: String): String? { ++ if (file !is KtFile){ ++ return null ++ } ++ val buffer = StringBuilder() ++ var changed = false ++ val fileText = file.text ++ val deducedBlockSelectionWidth = deduceBlockSelectionWidth(startOffsets, endOffsets, text) ++ ++ for (i in startOffsets.indices) { ++ if (i > 0) { ++ buffer.append('\n') // LF is added for block selection ++ } ++ ++ val fileRange = TextRange(startOffsets[i], endOffsets[i]) ++ ++ var givenTextOffset = fileRange.startOffset ++ while (givenTextOffset < fileRange.endOffset) { ++ val element: PsiElement? = file.findElementAt(givenTextOffset) ++ if (element == null) { ++ buffer.append(fileText.substring(givenTextOffset, fileRange.endOffset)) ++ break ++ } ++ val elTp = element.node.elementType ++ if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && !fileRange.contains(element.findContainingTemplate().range)) { ++ val tpEntry = element.parent as KtEscapeStringTemplateEntry ++ changed = true ++ buffer.append(tpEntry.unescapedValue) ++ givenTextOffset = element.endOffset ++ } ++ else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ //Process inner templates without escaping ++ val tpEntry = element.parent ++ val inter = fileRange.intersection(tpEntry.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ else { ++ val inter = fileRange.intersection(element.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ ++ } ++ val blockSelectionPadding = deducedBlockSelectionWidth - fileRange.length ++ for (j in 0..blockSelectionPadding - 1) { ++ buffer.append(' ') ++ } ++ ++ } ++ ++ return if (changed) buffer.toString() else null ++ } ++ ++ override fun preprocessOnPaste(project: Project, file: PsiFile, editor: Editor, text: String, rawText: RawText?): String { ++ if (file !is KtFile){ ++ return text ++ } ++ PsiDocumentManager.getInstance(project).commitDocument(editor.document) ++ val selectionModel = editor.selectionModel ++ val beginTp = file.getTemplateIfAtLiteral(selectionModel.selectionStart) ?: return text ++ val endTp = file.getTemplateIfAtLiteral(selectionModel.selectionEnd) ?: return text ++ if (beginTp.isSingleQuoted() != endTp.isSingleQuoted()) { ++ return text ++ } ++ ++ ++ return if (beginTp.isSingleQuoted()) { ++ TemplateTokenizer(text).map { ++ when (it) { ++ is LiteralChunk -> StringUtil.escaper(true, ""\$\"""").`fun`(it.text) ++ is EntryChunk -> it.text ++ is NewLineChunk -> ""\\n\""+\n \"""" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ else { ++ val tripleQuoteRe = Regex(""[\""]{3,}"") ++ TemplateTokenizer(text).map { chunk -> ++ when (chunk) { ++ is LiteralChunk -> chunk.text.replace(""\$"", ""\${'$'}"").let { escapedDollar -> ++ tripleQuoteRe.replace(escapedDollar) { ""\""\"""" + ""\${'\""'}"".repeat(it.value.count() - 2) } ++ } ++ ++ is EntryChunk -> chunk.text ++ is NewLineChunk -> ""\n"" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ ++ } ++ ++ ++} ++ ++private sealed class TemplateChunk ++private data class LiteralChunk(val text: String) : TemplateChunk() ++private data class EntryChunk(val text: String) : TemplateChunk() ++private class NewLineChunk : TemplateChunk()",Can be `object NewLineChunk`,2017-05-08 12:41:50 +846,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) { ++ KtTokens.REGULAR_STRING_PART, KtTokens.ESCAPE_SEQUENCE, KtTokens.LONG_TEMPLATE_ENTRY_START, KtTokens.SHORT_TEMPLATE_ENTRY_START -> at.parent.parent as? KtStringTemplateExpression ++ KtTokens.CLOSING_QUOTE -> if (offset == at.startOffset) at.parent as? KtStringTemplateExpression else null ++ else -> null ++ ++ } ++} ++ ++ ++//Copied from StringLiteralCopyPasteProcessor to avoid erroneous inheritance ++private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArray, text: String): Int { ++ val fragmentCount = startOffsets.size ++ assert(fragmentCount > 0) ++ var totalLength = fragmentCount - 1 // number of line breaks inserted between fragments ++ for (i in 0..fragmentCount - 1) { ++ totalLength += endOffsets[i] - startOffsets[i] ++ } ++ if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { ++ return (text.length + 1) / fragmentCount - 1 ++ } ++ else { ++ return -1 ++ } ++} ++ ++class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor { ++ override fun preprocessOnCopy(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray, text: String): String? { ++ if (file !is KtFile){ ++ return null ++ } ++ val buffer = StringBuilder() ++ var changed = false ++ val fileText = file.text ++ val deducedBlockSelectionWidth = deduceBlockSelectionWidth(startOffsets, endOffsets, text) ++ ++ for (i in startOffsets.indices) { ++ if (i > 0) { ++ buffer.append('\n') // LF is added for block selection ++ } ++ ++ val fileRange = TextRange(startOffsets[i], endOffsets[i]) ++ ++ var givenTextOffset = fileRange.startOffset ++ while (givenTextOffset < fileRange.endOffset) { ++ val element: PsiElement? = file.findElementAt(givenTextOffset) ++ if (element == null) { ++ buffer.append(fileText.substring(givenTextOffset, fileRange.endOffset)) ++ break ++ } ++ val elTp = element.node.elementType ++ if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && !fileRange.contains(element.findContainingTemplate().range)) { ++ val tpEntry = element.parent as KtEscapeStringTemplateEntry ++ changed = true ++ buffer.append(tpEntry.unescapedValue) ++ givenTextOffset = element.endOffset ++ } ++ else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ //Process inner templates without escaping ++ val tpEntry = element.parent ++ val inter = fileRange.intersection(tpEntry.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ else { ++ val inter = fileRange.intersection(element.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ ++ } ++ val blockSelectionPadding = deducedBlockSelectionWidth - fileRange.length ++ for (j in 0..blockSelectionPadding - 1) { ++ buffer.append(' ') ++ } ++ ++ } ++ ++ return if (changed) buffer.toString() else null ++ } ++ ++ override fun preprocessOnPaste(project: Project, file: PsiFile, editor: Editor, text: String, rawText: RawText?): String { ++ if (file !is KtFile){ ++ return text ++ } ++ PsiDocumentManager.getInstance(project).commitDocument(editor.document) ++ val selectionModel = editor.selectionModel ++ val beginTp = file.getTemplateIfAtLiteral(selectionModel.selectionStart) ?: return text ++ val endTp = file.getTemplateIfAtLiteral(selectionModel.selectionEnd) ?: return text ++ if (beginTp.isSingleQuoted() != endTp.isSingleQuoted()) { ++ return text ++ } ++ ++ ++ return if (beginTp.isSingleQuoted()) { ++ TemplateTokenizer(text).map { ++ when (it) { ++ is LiteralChunk -> StringUtil.escaper(true, ""\$\"""").`fun`(it.text) ++ is EntryChunk -> it.text ++ is NewLineChunk -> ""\\n\""+\n \"""" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ else { ++ val tripleQuoteRe = Regex(""[\""]{3,}"") ++ TemplateTokenizer(text).map { chunk -> ++ when (chunk) { ++ is LiteralChunk -> chunk.text.replace(""\$"", ""\${'$'}"").let { escapedDollar -> ++ tripleQuoteRe.replace(escapedDollar) { ""\""\"""" + ""\${'\""'}"".repeat(it.value.count() - 2) } ++ } ++ ++ is EntryChunk -> chunk.text ++ is NewLineChunk -> ""\n"" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ ++ } ++ ++ ++} ++ ++private sealed class TemplateChunk ++private data class LiteralChunk(val text: String) : TemplateChunk() ++private data class EntryChunk(val text: String) : TemplateChunk() ++private class NewLineChunk : TemplateChunk() ++ ++private class TemplateTokenizer(private val inputString: String) : Sequence {","I think this naming is kind of confusing; a tokenizer is something that returns a sequence, not something that is a sequence. I'd call it `TemplateTokenSequence`",2017-05-08 12:43:02 +847,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) { ++ KtTokens.REGULAR_STRING_PART, KtTokens.ESCAPE_SEQUENCE, KtTokens.LONG_TEMPLATE_ENTRY_START, KtTokens.SHORT_TEMPLATE_ENTRY_START -> at.parent.parent as? KtStringTemplateExpression ++ KtTokens.CLOSING_QUOTE -> if (offset == at.startOffset) at.parent as? KtStringTemplateExpression else null ++ else -> null ++ ++ } ++} ++ ++ ++//Copied from StringLiteralCopyPasteProcessor to avoid erroneous inheritance ++private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArray, text: String): Int { ++ val fragmentCount = startOffsets.size ++ assert(fragmentCount > 0) ++ var totalLength = fragmentCount - 1 // number of line breaks inserted between fragments ++ for (i in 0..fragmentCount - 1) { ++ totalLength += endOffsets[i] - startOffsets[i] ++ } ++ if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { ++ return (text.length + 1) / fragmentCount - 1 ++ } ++ else { ++ return -1 ++ } ++} ++ ++class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor { ++ override fun preprocessOnCopy(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray, text: String): String? { ++ if (file !is KtFile){ ++ return null ++ } ++ val buffer = StringBuilder() ++ var changed = false ++ val fileText = file.text ++ val deducedBlockSelectionWidth = deduceBlockSelectionWidth(startOffsets, endOffsets, text) ++ ++ for (i in startOffsets.indices) { ++ if (i > 0) { ++ buffer.append('\n') // LF is added for block selection ++ } ++ ++ val fileRange = TextRange(startOffsets[i], endOffsets[i]) ++ ++ var givenTextOffset = fileRange.startOffset ++ while (givenTextOffset < fileRange.endOffset) { ++ val element: PsiElement? = file.findElementAt(givenTextOffset) ++ if (element == null) { ++ buffer.append(fileText.substring(givenTextOffset, fileRange.endOffset)) ++ break ++ } ++ val elTp = element.node.elementType ++ if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && !fileRange.contains(element.findContainingTemplate().range)) { ++ val tpEntry = element.parent as KtEscapeStringTemplateEntry ++ changed = true ++ buffer.append(tpEntry.unescapedValue) ++ givenTextOffset = element.endOffset ++ } ++ else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ //Process inner templates without escaping ++ val tpEntry = element.parent ++ val inter = fileRange.intersection(tpEntry.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ else { ++ val inter = fileRange.intersection(element.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ ++ } ++ val blockSelectionPadding = deducedBlockSelectionWidth - fileRange.length ++ for (j in 0..blockSelectionPadding - 1) { ++ buffer.append(' ') ++ } ++ ++ } ++ ++ return if (changed) buffer.toString() else null ++ } ++ ++ override fun preprocessOnPaste(project: Project, file: PsiFile, editor: Editor, text: String, rawText: RawText?): String { ++ if (file !is KtFile){ ++ return text ++ } ++ PsiDocumentManager.getInstance(project).commitDocument(editor.document) ++ val selectionModel = editor.selectionModel ++ val beginTp = file.getTemplateIfAtLiteral(selectionModel.selectionStart) ?: return text ++ val endTp = file.getTemplateIfAtLiteral(selectionModel.selectionEnd) ?: return text ++ if (beginTp.isSingleQuoted() != endTp.isSingleQuoted()) { ++ return text ++ } ++ ++ ++ return if (beginTp.isSingleQuoted()) { ++ TemplateTokenizer(text).map { ++ when (it) { ++ is LiteralChunk -> StringUtil.escaper(true, ""\$\"""").`fun`(it.text) ++ is EntryChunk -> it.text ++ is NewLineChunk -> ""\\n\""+\n \"""" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ else { ++ val tripleQuoteRe = Regex(""[\""]{3,}"") ++ TemplateTokenizer(text).map { chunk -> ++ when (chunk) { ++ is LiteralChunk -> chunk.text.replace(""\$"", ""\${'$'}"").let { escapedDollar -> ++ tripleQuoteRe.replace(escapedDollar) { ""\""\"""" + ""\${'\""'}"".repeat(it.value.count() - 2) } ++ } ++ ++ is EntryChunk -> chunk.text ++ is NewLineChunk -> ""\n"" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ ++ } ++ ++ ++} ++ ++private sealed class TemplateChunk ++private data class LiteralChunk(val text: String) : TemplateChunk() ++private data class EntryChunk(val text: String) : TemplateChunk() ++private class NewLineChunk : TemplateChunk() ++ ++private class TemplateTokenizer(private val inputString: String) : Sequence { ++ ++ private fun String.guessIsTemplateEntryStart(): Boolean = ++ if (this.startsWith(""\${"")) { ++ true ++ } ++ else if (this.length > 1 && this[0] == '$'){ ++ KotlinLexer().apply { start(this@guessIsTemplateEntryStart.substring(1)) }.tokenType == KtTokens.IDENTIFIER",Better to declare the result of `substring` as a variable outside of the `apply` block.,2017-05-08 12:44:14 +849,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) { ++ KtTokens.REGULAR_STRING_PART, KtTokens.ESCAPE_SEQUENCE, KtTokens.LONG_TEMPLATE_ENTRY_START, KtTokens.SHORT_TEMPLATE_ENTRY_START -> at.parent.parent as? KtStringTemplateExpression ++ KtTokens.CLOSING_QUOTE -> if (offset == at.startOffset) at.parent as? KtStringTemplateExpression else null ++ else -> null ++ ++ } ++} ++ ++ ++//Copied from StringLiteralCopyPasteProcessor to avoid erroneous inheritance ++private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArray, text: String): Int { ++ val fragmentCount = startOffsets.size ++ assert(fragmentCount > 0) ++ var totalLength = fragmentCount - 1 // number of line breaks inserted between fragments ++ for (i in 0..fragmentCount - 1) { ++ totalLength += endOffsets[i] - startOffsets[i] ++ } ++ if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { ++ return (text.length + 1) / fragmentCount - 1 ++ } ++ else { ++ return -1 ++ } ++} ++ ++class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor { ++ override fun preprocessOnCopy(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray, text: String): String? { ++ if (file !is KtFile){ ++ return null ++ } ++ val buffer = StringBuilder() ++ var changed = false ++ val fileText = file.text ++ val deducedBlockSelectionWidth = deduceBlockSelectionWidth(startOffsets, endOffsets, text) ++ ++ for (i in startOffsets.indices) { ++ if (i > 0) { ++ buffer.append('\n') // LF is added for block selection ++ } ++ ++ val fileRange = TextRange(startOffsets[i], endOffsets[i]) ++ ++ var givenTextOffset = fileRange.startOffset ++ while (givenTextOffset < fileRange.endOffset) { ++ val element: PsiElement? = file.findElementAt(givenTextOffset) ++ if (element == null) { ++ buffer.append(fileText.substring(givenTextOffset, fileRange.endOffset)) ++ break ++ } ++ val elTp = element.node.elementType ++ if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && !fileRange.contains(element.findContainingTemplate().range)) { ++ val tpEntry = element.parent as KtEscapeStringTemplateEntry ++ changed = true ++ buffer.append(tpEntry.unescapedValue) ++ givenTextOffset = element.endOffset ++ } ++ else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ //Process inner templates without escaping ++ val tpEntry = element.parent ++ val inter = fileRange.intersection(tpEntry.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ else { ++ val inter = fileRange.intersection(element.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ ++ } ++ val blockSelectionPadding = deducedBlockSelectionWidth - fileRange.length ++ for (j in 0..blockSelectionPadding - 1) { ++ buffer.append(' ') ++ } ++ ++ } ++ ++ return if (changed) buffer.toString() else null ++ } ++ ++ override fun preprocessOnPaste(project: Project, file: PsiFile, editor: Editor, text: String, rawText: RawText?): String { ++ if (file !is KtFile){ ++ return text ++ } ++ PsiDocumentManager.getInstance(project).commitDocument(editor.document) ++ val selectionModel = editor.selectionModel ++ val beginTp = file.getTemplateIfAtLiteral(selectionModel.selectionStart) ?: return text ++ val endTp = file.getTemplateIfAtLiteral(selectionModel.selectionEnd) ?: return text ++ if (beginTp.isSingleQuoted() != endTp.isSingleQuoted()) { ++ return text ++ } ++ ++ ++ return if (beginTp.isSingleQuoted()) { ++ TemplateTokenizer(text).map { ++ when (it) { ++ is LiteralChunk -> StringUtil.escaper(true, ""\$\"""").`fun`(it.text) ++ is EntryChunk -> it.text ++ is NewLineChunk -> ""\\n\""+\n \"""" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ else { ++ val tripleQuoteRe = Regex(""[\""]{3,}"") ++ TemplateTokenizer(text).map { chunk -> ++ when (chunk) { ++ is LiteralChunk -> chunk.text.replace(""\$"", ""\${'$'}"").let { escapedDollar -> ++ tripleQuoteRe.replace(escapedDollar) { ""\""\"""" + ""\${'\""'}"".repeat(it.value.count() - 2) } ++ } ++ ++ is EntryChunk -> chunk.text ++ is NewLineChunk -> ""\n"" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ ++ } ++ ++ ++} ++ ++private sealed class TemplateChunk ++private data class LiteralChunk(val text: String) : TemplateChunk() ++private data class EntryChunk(val text: String) : TemplateChunk() ++private class NewLineChunk : TemplateChunk() ++ ++private class TemplateTokenizer(private val inputString: String) : Sequence { ++ ++ private fun String.guessIsTemplateEntryStart(): Boolean = ++ if (this.startsWith(""\${"")) { ++ true ++ } ++ else if (this.length > 1 && this[0] == '$'){ ++ KotlinLexer().apply { start(this@guessIsTemplateEntryStart.substring(1)) }.tokenType == KtTokens.IDENTIFIER ++ } ++ else { ++ false ++ } ++ ++ private fun findTemplateEntryEnd(input: String, from: Int): Int{ ++ val wrapped = '""' + input.substring(from) + '""' ++ val lexer = KotlinLexer().apply { start(wrapped) }.apply { advance() } ++ ++ if (lexer.tokenType == KtTokens.SHORT_TEMPLATE_ENTRY_START){ ++ lexer.advance() ++ return if (lexer.tokenType == KtTokens.IDENTIFIER){ ++ from + lexer.tokenEnd -1 ++ } else{ ++ -1 ++ } ++ } ++ else if(lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ var depth = 0 ++ while (lexer.tokenType != null) { ++ if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ depth++ ++ } ++ else if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END) { ++ depth-- ++ if (depth == 0) { ++ return from + lexer.currentPosition.offset - 1 ++ } ++ } ++ lexer.advance() ++ } ++ return -1 ++ } ++ else { ++ return -1 ++ } ++ } ++ ++ private suspend fun SequenceBuilder.yieldLiteral(chunk: String) { ++ ++ val splitLines = LineTokenizer.tokenize(chunk, false, true) ++ for (i in 0..splitLines.size - 1) { ++ if (i != 0) { ++ yield(NewLineChunk()) ++ } ++ splitLines[i].takeIf { !it.isEmpty() }?.let { yield(LiteralChunk(it)) } ++ } ++ ++ } ++ ++ private fun iterTemplateChunks(): Iterator { ++ if (inputString.isEmpty()) { ++ return emptySequence().iterator() ++ } ++ return buildIterator { ++ var from = 0 ++ var to = 0 ++ while (to < inputString.length) { ++ val c = inputString[to] ++ if (c == '\\') { ++ to += 1 ++ if (to < inputString.length) ++ to += 1",I think this assumes that all escapes are single-character? That's not true; there are also `\uxxxx` escape sequences.,2017-05-08 12:48:33 +848,"@@ -0,0 +1,285 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.editor ++ ++import com.intellij.codeInsight.editorActions.CopyPastePreProcessor ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.editor.RawText ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.openapi.util.text.LineTokenizer ++import com.intellij.openapi.util.text.StringUtil ++import com.intellij.psi.PsiDocumentManager ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.editor.fixers.range ++import org.jetbrains.kotlin.lexer.KotlinLexer ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtStringTemplateEntry ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import kotlin.coroutines.experimental.SequenceBuilder ++import kotlin.coroutines.experimental.buildIterator ++ ++private fun PsiElement.findContainingTemplate(): PsiElement { ++ val parent = this.parent ++ @Suppress(""IfThenToElvis"") ++ return if (parent is KtStringTemplateEntry) parent.parent else parent ++} ++ ++private fun PsiFile.getTemplateIfAtLiteral(offset: Int): KtStringTemplateExpression? { ++ val at = this.findElementAt(offset) ?: return null ++ return when (at.node?.elementType) { ++ KtTokens.REGULAR_STRING_PART, KtTokens.ESCAPE_SEQUENCE, KtTokens.LONG_TEMPLATE_ENTRY_START, KtTokens.SHORT_TEMPLATE_ENTRY_START -> at.parent.parent as? KtStringTemplateExpression ++ KtTokens.CLOSING_QUOTE -> if (offset == at.startOffset) at.parent as? KtStringTemplateExpression else null ++ else -> null ++ ++ } ++} ++ ++ ++//Copied from StringLiteralCopyPasteProcessor to avoid erroneous inheritance ++private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArray, text: String): Int { ++ val fragmentCount = startOffsets.size ++ assert(fragmentCount > 0) ++ var totalLength = fragmentCount - 1 // number of line breaks inserted between fragments ++ for (i in 0..fragmentCount - 1) { ++ totalLength += endOffsets[i] - startOffsets[i] ++ } ++ if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { ++ return (text.length + 1) / fragmentCount - 1 ++ } ++ else { ++ return -1 ++ } ++} ++ ++class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor { ++ override fun preprocessOnCopy(file: PsiFile, startOffsets: IntArray, endOffsets: IntArray, text: String): String? { ++ if (file !is KtFile){ ++ return null ++ } ++ val buffer = StringBuilder() ++ var changed = false ++ val fileText = file.text ++ val deducedBlockSelectionWidth = deduceBlockSelectionWidth(startOffsets, endOffsets, text) ++ ++ for (i in startOffsets.indices) { ++ if (i > 0) { ++ buffer.append('\n') // LF is added for block selection ++ } ++ ++ val fileRange = TextRange(startOffsets[i], endOffsets[i]) ++ ++ var givenTextOffset = fileRange.startOffset ++ while (givenTextOffset < fileRange.endOffset) { ++ val element: PsiElement? = file.findElementAt(givenTextOffset) ++ if (element == null) { ++ buffer.append(fileText.substring(givenTextOffset, fileRange.endOffset)) ++ break ++ } ++ val elTp = element.node.elementType ++ if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && !fileRange.contains(element.findContainingTemplate().range)) { ++ val tpEntry = element.parent as KtEscapeStringTemplateEntry ++ changed = true ++ buffer.append(tpEntry.unescapedValue) ++ givenTextOffset = element.endOffset ++ } ++ else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ //Process inner templates without escaping ++ val tpEntry = element.parent ++ val inter = fileRange.intersection(tpEntry.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ else { ++ val inter = fileRange.intersection(element.range)!! ++ buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) ++ givenTextOffset = inter.endOffset ++ } ++ ++ } ++ val blockSelectionPadding = deducedBlockSelectionWidth - fileRange.length ++ for (j in 0..blockSelectionPadding - 1) { ++ buffer.append(' ') ++ } ++ ++ } ++ ++ return if (changed) buffer.toString() else null ++ } ++ ++ override fun preprocessOnPaste(project: Project, file: PsiFile, editor: Editor, text: String, rawText: RawText?): String { ++ if (file !is KtFile){ ++ return text ++ } ++ PsiDocumentManager.getInstance(project).commitDocument(editor.document) ++ val selectionModel = editor.selectionModel ++ val beginTp = file.getTemplateIfAtLiteral(selectionModel.selectionStart) ?: return text ++ val endTp = file.getTemplateIfAtLiteral(selectionModel.selectionEnd) ?: return text ++ if (beginTp.isSingleQuoted() != endTp.isSingleQuoted()) { ++ return text ++ } ++ ++ ++ return if (beginTp.isSingleQuoted()) { ++ TemplateTokenizer(text).map { ++ when (it) { ++ is LiteralChunk -> StringUtil.escaper(true, ""\$\"""").`fun`(it.text) ++ is EntryChunk -> it.text ++ is NewLineChunk -> ""\\n\""+\n \"""" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ else { ++ val tripleQuoteRe = Regex(""[\""]{3,}"") ++ TemplateTokenizer(text).map { chunk -> ++ when (chunk) { ++ is LiteralChunk -> chunk.text.replace(""\$"", ""\${'$'}"").let { escapedDollar -> ++ tripleQuoteRe.replace(escapedDollar) { ""\""\"""" + ""\${'\""'}"".repeat(it.value.count() - 2) } ++ } ++ ++ is EntryChunk -> chunk.text ++ is NewLineChunk -> ""\n"" ++ ++ } ++ }.joinToString(separator = """") ++ } ++ ++ } ++ ++ ++} ++ ++private sealed class TemplateChunk ++private data class LiteralChunk(val text: String) : TemplateChunk() ++private data class EntryChunk(val text: String) : TemplateChunk() ++private class NewLineChunk : TemplateChunk() ++ ++private class TemplateTokenizer(private val inputString: String) : Sequence { ++ ++ private fun String.guessIsTemplateEntryStart(): Boolean = ++ if (this.startsWith(""\${"")) { ++ true ++ } ++ else if (this.length > 1 && this[0] == '$'){ ++ KotlinLexer().apply { start(this@guessIsTemplateEntryStart.substring(1)) }.tokenType == KtTokens.IDENTIFIER ++ } ++ else { ++ false ++ } ++ ++ private fun findTemplateEntryEnd(input: String, from: Int): Int{ ++ val wrapped = '""' + input.substring(from) + '""' ++ val lexer = KotlinLexer().apply { start(wrapped) }.apply { advance() } ++ ++ if (lexer.tokenType == KtTokens.SHORT_TEMPLATE_ENTRY_START){ ++ lexer.advance() ++ return if (lexer.tokenType == KtTokens.IDENTIFIER){ ++ from + lexer.tokenEnd -1 ++ } else{ ++ -1 ++ } ++ } ++ else if(lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ var depth = 0 ++ while (lexer.tokenType != null) { ++ if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) { ++ depth++ ++ } ++ else if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END) { ++ depth-- ++ if (depth == 0) { ++ return from + lexer.currentPosition.offset - 1 ++ } ++ } ++ lexer.advance() ++ } ++ return -1 ++ } ++ else { ++ return -1 ++ } ++ } ++ ++ private suspend fun SequenceBuilder.yieldLiteral(chunk: String) { ++ ++ val splitLines = LineTokenizer.tokenize(chunk, false, true) ++ for (i in 0..splitLines.size - 1) { ++ if (i != 0) { ++ yield(NewLineChunk()) ++ } ++ splitLines[i].takeIf { !it.isEmpty() }?.let { yield(LiteralChunk(it)) } ++ } ++ ++ } ++ ++ private fun iterTemplateChunks(): Iterator { ++ if (inputString.isEmpty()) { ++ return emptySequence().iterator() ++ } ++ return buildIterator { ++ var from = 0 ++ var to = 0 ++ while (to < inputString.length) { ++ val c = inputString[to] ++ if (c == '\\') { ++ to += 1 ++ if (to < inputString.length) ++ to += 1 ++ continue ++ ++ } ++ when (c) {",No reason to use `when` here; `if` would be cleaner.,2017-05-08 12:45:31 +901,"@@ -0,0 +1,3 @@ ++// INTENTION_TEXT: ""Convert to sealed class""","Since you aren't changing the intention text dynamically, there's no need to include INTENTION_TEXT in testdata files.",2017-07-17 11:17:40 +902,"@@ -0,0 +1,3 @@ ++@JvmStatic","The template shows a top-level method, not a method inside an `object`. Please update it to show what the intention action actually does.",2017-07-17 11:20:35 +100,"@@ -0,0 +1,3 @@ ++[3] ++ ++[3, 5]","Please update this file to be exactly the result of your intention on `before.kt.template`. Also you can use `` tag to highlight the place where the user should put his attention +",2014-02-06 14:38:50 +223,"@@ -0,0 +1,3 @@ ++for ((i,x) in foo.withIndices()) {","Please add a whitespace after the comma +",2014-04-30 19:19:20 +211,"@@ -0,0 +1,3 @@ ++fun foo(a: String?, b: String?) { ++ a?.equals(b) ?: b.identityEquals(null) ++}","Please, add test for the case of non-nullable receiver +",2014-04-23 14:22:32 +84,"@@ -0,0 +1,3 @@ ++fun foo(x: Boolean) : Boolean { ++ return x || x || x","This behavior is objectionable: order of predicates evaluation can change program behavior, when evaluated expressions have side effects. I'll disable intention in this case. +",2013-07-08 15:18:18 +805,"@@ -0,0 +1,30 @@ ++/*","Consider merging small and relevant declarations together into one file, e.g. `JavaType` implementations into `symbolBasedTypes.kt`, `JavaAnnotationArgument` implementations into `symbolBasedAnnotationArguments.kt` and so on. I think it'd be more readable in the end",2017-04-25 12:19:05 +720,"@@ -0,0 +1,30 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaEnumValueAnnotationArgument ++import org.jetbrains.kotlin.name.FqName ++import javax.lang.model.element.VariableElement ++ ++class JavacReferenceAnnotationArgument(val element: VariableElement, ++ javac: Javac) : JavacAnnotationArgument(FqName(element.simpleName.toString()), javac), ++ JavaEnumValueAnnotationArgument { ++ ++ override fun resolve() = JavacField(element, javac)","In NB plugin you're using containing class at this point, but here you aren't. Are you sure it's not a mistake?",2017-04-05 15:10:31 +803,"@@ -0,0 +1,30 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationAsAnnotationArgument ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.AnnotationMirror ++ ++class SymbolBasedAnnotationAsAnnotationArgument(val mirror: AnnotationMirror,","I'd assume that all `SymbolBased*AnnotationArgument`s are subclasses of `SymbolBasedAnnotationArgument`, but only one of them is (`SymbolBasedReferenceAnnotationArgument`). I suggest either inheriting all of them from `SymbolBasedAnnotationArgument`, or getting rid of the latter altogether",2017-04-25 12:08:18 +809,"@@ -0,0 +1,30 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaArrayType ++import javax.lang.model.type.ArrayType ++import javax.lang.model.type.TypeMirror ++ ++class SymbolBasedArrayType(typeMirror: T,","Instead of generic type parameter, inherit from `SymbolBasedType`, cast `typeMirror` to `ArrayType` once at creation site",2017-04-25 12:26:46 +394,"@@ -0,0 +1,304 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. One of the problems with them is that they should be effectively duplicated in reflection which means a lot of physical classes in the runtime.","""in the runtime"" -> ""at runtime""? +Имеется в виду ""во время выполнения программы""? +",2015-07-27 18:37:05 +395,"@@ -0,0 +1,304 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. One of the problems with them is that they should be effectively duplicated in reflection which means a lot of physical classes in the runtime. ++* Make extension functions coercible to normal functions (with an extra parameter), so that it's possible to do `listOfStrings.map(String::length)`","""coercible"" usually assumes some transformation of the value representation to fit to a new type. If it's exactly the same object, just viewed as an instance of a new type, then maybe it would be better to say ""implicitly convertible"" or ""assignable""? +",2015-07-27 18:40:57 +396,"@@ -0,0 +1,304 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. One of the problems with them is that they should be effectively duplicated in reflection which means a lot of physical classes in the runtime. ++* Make extension functions coercible to normal functions (with an extra parameter), so that it's possible to do `listOfStrings.map(String::length)` ++* Allow functions with more than 23 parameters, theoretically any number of parameters (in practice 255 on JVM). ++* At the same time, allow to implement Kotlin functions easily from Java: `new Function2() { ... }` and overriding `invoke` only would be the best.","I do not get the meaning of ""overriding `invoke` only would be the best"". +",2015-07-27 18:42:14 +397,"@@ -0,0 +1,304 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. One of the problems with them is that they should be effectively duplicated in reflection which means a lot of physical classes in the runtime. ++* Make extension functions coercible to normal functions (with an extra parameter), so that it's possible to do `listOfStrings.map(String::length)` ++* Allow functions with more than 23 parameters, theoretically any number of parameters (in practice 255 on JVM). ++* At the same time, allow to implement Kotlin functions easily from Java: `new Function2() { ... }` and overriding `invoke` only would be the best. ++Enabling SAM conversions on Java 8 would also be terrific. ++ ++## Brief solution overview ++ ++* Treat extension functions almost like non-extension functions with one extra parameter, allowing to use them almost interchangeably. ++* Introduce a physical class `Function` and unlimited number of *fictitious* (synthetic) classes `Function0`, `Function1`, ... in the compiler front-end ++* On JVM, introduce `Function0`..`Function22`, which are optimized in a certain way, ++and `FunctionN` for functions with 23+ parameters. ++When passing a lambda to Kotlin from Java, one will need to implement one of these interfaces. ++* Also on JVM (under the hood) add abstract `FunctionImpl` which implements all of `Fun0`..`Fun22` and `FunN`","What is `Fun0`? +",2015-07-27 18:44:14 +398,"@@ -0,0 +1,304 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. One of the problems with them is that they should be effectively duplicated in reflection which means a lot of physical classes in the runtime. ++* Make extension functions coercible to normal functions (with an extra parameter), so that it's possible to do `listOfStrings.map(String::length)` ++* Allow functions with more than 23 parameters, theoretically any number of parameters (in practice 255 on JVM). ++* At the same time, allow to implement Kotlin functions easily from Java: `new Function2() { ... }` and overriding `invoke` only would be the best. ++Enabling SAM conversions on Java 8 would also be terrific. ++ ++## Brief solution overview ++ ++* Treat extension functions almost like non-extension functions with one extra parameter, allowing to use them almost interchangeably. ++* Introduce a physical class `Function` and unlimited number of *fictitious* (synthetic) classes `Function0`, `Function1`, ... in the compiler front-end ++* On JVM, introduce `Function0`..`Function22`, which are optimized in a certain way, ++and `FunctionN` for functions with 23+ parameters. ++When passing a lambda to Kotlin from Java, one will need to implement one of these interfaces. ++* Also on JVM (under the hood) add abstract `FunctionImpl` which implements all of `Fun0`..`Fun22` and `FunN` ++(throwing exceptions), and which knows its arity. ++Kotlin lambdas are translated to subclasses of this abstract class, passing the correct arity to the super constructor. ++* Provide a way to get arity of an arbitrary `Function` object (pretty straightforward). ++* Hack `is/as Function5` on any numbered function in codegen (and probably `KClass.cast()` in reflection) to check against `Function` and its arity.","So, is it `Function` or `FunctionImpl` who knows the function arity? For which type are we going to check in `is` operator? +",2015-07-27 18:47:04 +399,"@@ -0,0 +1,304 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. One of the problems with them is that they should be effectively duplicated in reflection which means a lot of physical classes in the runtime. ++* Make extension functions coercible to normal functions (with an extra parameter), so that it's possible to do `listOfStrings.map(String::length)` ++* Allow functions with more than 23 parameters, theoretically any number of parameters (in practice 255 on JVM). ++* At the same time, allow to implement Kotlin functions easily from Java: `new Function2() { ... }` and overriding `invoke` only would be the best. ++Enabling SAM conversions on Java 8 would also be terrific. ++ ++## Brief solution overview ++ ++* Treat extension functions almost like non-extension functions with one extra parameter, allowing to use them almost interchangeably. ++* Introduce a physical class `Function` and unlimited number of *fictitious* (synthetic) classes `Function0`, `Function1`, ... in the compiler front-end ++* On JVM, introduce `Function0`..`Function22`, which are optimized in a certain way, ++and `FunctionN` for functions with 23+ parameters. ++When passing a lambda to Kotlin from Java, one will need to implement one of these interfaces. ++* Also on JVM (under the hood) add abstract `FunctionImpl` which implements all of `Fun0`..`Fun22` and `FunN` ++(throwing exceptions), and which knows its arity. ++Kotlin lambdas are translated to subclasses of this abstract class, passing the correct arity to the super constructor. ++* Provide a way to get arity of an arbitrary `Function` object (pretty straightforward). ++* Hack `is/as Function5` on any numbered function in codegen (and probably `KClass.cast()` in reflection) to check against `Function` and its arity. ++ ++## Extension functions ++ ++Extension function type `T.(P) -> R` is now just a shorthand for `@kotlin.extension Function2`. ++`kotlin.extension` is a **type annotation** defined in built-ins. ++So effectively functions and extension functions now have the same type, ++which means that everything which takes a function will work with an extension function and vice versa. ++ ++To prevent unpleasant ambiguities, we introduce additional restrictions: ++* A value of an extension function type cannot be **called** as a function, and a value of a non-extension ++function type cannot be called as an extension. This requires an additional diagnostic which is only fired ++when a call is resolved to the `invoke` with the wrong extension-ness. ++* If an extension function **literal** argument has some shape (its parameters are written out explicitly ++in the code and it's evident that there is or there isn't a receiver parameter), this shape must exactly match","What could make it evident that there is or there isn't a receiver parameter? +",2015-07-27 18:50:04 +400,"@@ -0,0 +1,304 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. One of the problems with them is that they should be effectively duplicated in reflection which means a lot of physical classes in the runtime. ++* Make extension functions coercible to normal functions (with an extra parameter), so that it's possible to do `listOfStrings.map(String::length)` ++* Allow functions with more than 23 parameters, theoretically any number of parameters (in practice 255 on JVM). ++* At the same time, allow to implement Kotlin functions easily from Java: `new Function2() { ... }` and overriding `invoke` only would be the best. ++Enabling SAM conversions on Java 8 would also be terrific. ++ ++## Brief solution overview ++ ++* Treat extension functions almost like non-extension functions with one extra parameter, allowing to use them almost interchangeably. ++* Introduce a physical class `Function` and unlimited number of *fictitious* (synthetic) classes `Function0`, `Function1`, ... in the compiler front-end ++* On JVM, introduce `Function0`..`Function22`, which are optimized in a certain way, ++and `FunctionN` for functions with 23+ parameters. ++When passing a lambda to Kotlin from Java, one will need to implement one of these interfaces. ++* Also on JVM (under the hood) add abstract `FunctionImpl` which implements all of `Fun0`..`Fun22` and `FunN` ++(throwing exceptions), and which knows its arity. ++Kotlin lambdas are translated to subclasses of this abstract class, passing the correct arity to the super constructor. ++* Provide a way to get arity of an arbitrary `Function` object (pretty straightforward). ++* Hack `is/as Function5` on any numbered function in codegen (and probably `KClass.cast()` in reflection) to check against `Function` and its arity. ++ ++## Extension functions ++ ++Extension function type `T.(P) -> R` is now just a shorthand for `@kotlin.extension Function2`. ++`kotlin.extension` is a **type annotation** defined in built-ins. ++So effectively functions and extension functions now have the same type, ++which means that everything which takes a function will work with an extension function and vice versa. ++ ++To prevent unpleasant ambiguities, we introduce additional restrictions: ++* A value of an extension function type cannot be **called** as a function, and a value of a non-extension ++function type cannot be called as an extension. This requires an additional diagnostic which is only fired ++when a call is resolved to the `invoke` with the wrong extension-ness. ++* If an extension function **literal** argument has some shape (its parameters are written out explicitly ++in the code and it's evident that there is or there isn't a receiver parameter), this shape must exactly match ++the extension-ness of the corresponding parameter. You can't pass an extension function **literal** ++where a function is expected and vice versa. The same holds for function expressions. ++If you really want to do that, change the shape or use the `as` operator. ++ ++So basically you can now safely coerce values between function and extension function types, ++but still should invoke them in the format which you specified in their type (with or without `@extension`). ++ ++With this we'll get rid of classes `ExtensionFunction0`, `ExtensionFunction1`, ... ++and the rest of this article will deal only with usual functions. ++ ++## Function0, Function1, ... types ++ ++The arity of the functional interface that the type checker can create in theory **is not limited** to any number, ++but in practice should be limited to 255 on JVM. ++ ++These interfaces are named `kotlin.Function0`, `kotlin.Function1`, ..., `kotlin.Function42`, ... ++They are *fictitious*, which means they have no sources and no runtime representation. ++Type checker creates the corresponding descriptors on demand, IDE creates corresponding source files on demand as well. ++Each of them inherits from `kotlin.Function` (described below) and contains only two functions, ++both of which should be synthetically produced by the compiler: ++* (declaration) `invoke` with no receiver, with the corresponding number of parameters and return type. ++* (synthesized) `invoke` with first type parameter as the extension receiver type, and the rest as parameters and return type.","""first type parameter""? Are you talking about ``? +",2015-07-27 18:54:14 +719,"@@ -0,0 +1,31 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.builtins.PrimitiveType ++import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType ++import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType ++import javax.lang.model.type.TypeMirror ++ ++class JavacPrimitiveType(typeMirror: T, ++ javac: Javac) : JavacType(typeMirror, javac), JavaPrimitiveType { ++ ++ override val type: PrimitiveType? ++ get() = if (""void"" == typeMirror.toString()) null else JvmPrimitiveType.get(typeMirror.toString()).primitiveType",You can extract `typeMirror.toString()`,2017-04-05 15:09:04 +830,"@@ -0,0 +1,31 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++import org.jetbrains.kotlin.name.FqName ++ ++open class TreeBasedAnnotationArgument(val tree: JCTree.JCExpression, ++ fqName: FqName,",`Name` should be enough here as well,2017-04-25 16:28:33 +462,"@@ -0,0 +1,313 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.reflect.KMutableProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++public val COMPILE_DAEMON_TIMEOUT_INFINITE_S: Int = 0 ++public val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++//open class PropExtractor>(val dest: C, ++// val prop: P, ++// val name: String, ++// val convert: ((v: V) -> String?) = { it.toString() }, ++// val skipIf: ((v: V) -> Boolean) = { false }, ++// val mergeWithDelimiter: String? = null) ++//{ ++// constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++// open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++// when { ++// skipIf(prop.get(dest)) -> listOf() ++// mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++// else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++// } ++//} ++// ++//class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++// : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++// ++//class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++// override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++//} ++// ++// ++//open class PropParser>(val dest: C, ++// val prop: P, alternativeNames: List, ++// val parse: (s: String) -> V, ++// val allowMergedArg: Boolean = false) { ++// val names = listOf(prop.name) + alternativeNames ++// constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++// fun apply(s: String) = prop.set(dest, parse(s)) ++//} ++// ++//class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++// ++//class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++// fun add(s: String) { prop.get(dest).add(s) } ++//}","let's drop it +",2015-08-31 12:29:46 +460,"@@ -0,0 +1,313 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.reflect.KMutableProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++public val COMPILE_DAEMON_TIMEOUT_INFINITE_S: Int = 0 ++public val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++//open class PropExtractor>(val dest: C, ++// val prop: P, ++// val name: String, ++// val convert: ((v: V) -> String?) = { it.toString() }, ++// val skipIf: ((v: V) -> Boolean) = { false }, ++// val mergeWithDelimiter: String? = null) ++//{ ++// constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++// open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++// when { ++// skipIf(prop.get(dest)) -> listOf() ++// mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++// else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++// } ++//} ++// ++//class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++// : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++// ++//class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++// override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++//} ++// ++// ++//open class PropParser>(val dest: C, ++// val prop: P, alternativeNames: List, ++// val parse: (s: String) -> V, ++// val allowMergedArg: Boolean = false) { ++// val names = listOf(prop.name) + alternativeNames ++// constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++// fun apply(s: String) = prop.set(dest, parse(s)) ++//} ++// ++//class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++// ++//class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++// fun add(s: String) { prop.get(dest).add(s) } ++//} ++ ++// -------------------------------------------------------- ++ ++open class PropMapper>(val dest: C, ++ val prop: P, ++ val names: List = listOf(prop.name), ++ val fromString: (s: String) -> V, ++ val toString: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeDelimiter: String? = null) ++{ ++ open fun toArgs(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeDelimiter != null -> listOf(prefix + names.first() + mergeDelimiter + toString(prop.get(dest))).filterNotNull()","nothing to filter out by `filterNotNull` +",2015-08-31 11:42:08 +461,"@@ -0,0 +1,313 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.File ++import java.io.Serializable ++import java.lang.management.ManagementFactory ++import java.security.DigestInputStream ++import java.security.MessageDigest ++import kotlin.reflect.KMutableProperty1 ++ ++ ++public val COMPILER_JAR_NAME: String = ""kotlin-compiler.jar"" ++public val COMPILER_SERVICE_RMI_NAME: String = ""KotlinJvmCompilerService"" ++public val COMPILER_DAEMON_CLASS_FQN: String = ""org.jetbrains.kotlin.rmi.service.CompileDaemon"" ++public val COMPILE_DAEMON_DEFAULT_PORT: Int = 17031 ++public val COMPILE_DAEMON_ENABLED_PROPERTY: String =""kotlin.daemon.enabled"" ++public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String =""kotlin.daemon.jvm.options"" ++public val COMPILE_DAEMON_OPTIONS_PROPERTY: String =""kotlin.daemon.options"" ++public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String =""--daemon-"" ++public val COMPILE_DAEMON_TIMEOUT_INFINITE_S: Int = 0 ++public val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L ++ ++val COMPILER_ID_DIGEST = ""MD5"" ++ ++//open class PropExtractor>(val dest: C, ++// val prop: P, ++// val name: String, ++// val convert: ((v: V) -> String?) = { it.toString() }, ++// val skipIf: ((v: V) -> Boolean) = { false }, ++// val mergeWithDelimiter: String? = null) ++//{ ++// constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) ++// open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++// when { ++// skipIf(prop.get(dest)) -> listOf() ++// mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() ++// else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() ++// } ++//} ++// ++//class BoolPropExtractor>(dest: C, prop: P, name: String? = null) ++// : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) ++// ++//class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { ++// override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } ++//} ++// ++// ++//open class PropParser>(val dest: C, ++// val prop: P, alternativeNames: List, ++// val parse: (s: String) -> V, ++// val allowMergedArg: Boolean = false) { ++// val names = listOf(prop.name) + alternativeNames ++// constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) ++// fun apply(s: String) = prop.set(dest, parse(s)) ++//} ++// ++//class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) ++// ++//class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { ++// fun add(s: String) { prop.get(dest).add(s) } ++//} ++ ++// -------------------------------------------------------- ++ ++open class PropMapper>(val dest: C, ++ val prop: P, ++ val names: List = listOf(prop.name), ++ val fromString: (s: String) -> V, ++ val toString: ((v: V) -> String?) = { it.toString() }, ++ val skipIf: ((v: V) -> Boolean) = { false }, ++ val mergeDelimiter: String? = null) ++{ ++ open fun toArgs(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = ++ when { ++ skipIf(prop.get(dest)) -> listOf() ++ mergeDelimiter != null -> listOf(prefix + names.first() + mergeDelimiter + toString(prop.get(dest))).filterNotNull() ++ else -> listOf(prefix + names.first(), toString(prop.get(dest))).filterNotNull() ++ } ++ fun apply(s: String) = prop.set(dest, fromString(s)) ++} ++ ++class StringPropMapper>(dest: C, ++ prop: P, ++ names: List = listOf(), ++ fromString: ((String) -> String) = { it }, ++ toString: ((String) -> String?) = { it.toString() }, ++ skipIf: ((String) -> Boolean) = { it.isEmpty() }, ++ mergeDelimiter: String? = null) ++: PropMapper(dest = dest, prop = prop, names = if (names.any()) names else listOf(prop.name), ++ fromString = fromString, toString = toString, skipIf = skipIf, mergeDelimiter = mergeDelimiter) ++ ++class BoolPropMapper>(dest: C, prop: P, names: List = listOf()) ++ : PropMapper(dest = dest, prop = prop, names = if (names.any()) names else listOf(prop.name), ++ fromString = { true }, toString = { null }, skipIf = { !prop.get(dest) }) ++ ++class RestPropMapper>>(dest: C, prop: P) ++ : PropMapper, P>(dest = dest, prop = prop, toString = { null }, fromString = { arrayListOf() }) ++{ ++ override fun toArgs(prefix: String): List = prop.get(dest).map { prefix + it } ++ fun add(s: String) { prop.get(dest).add(s) } ++} ++ ++// ------------------------------------------ ++ ++fun Iterable.filterExtractProps(propMappers: List>, prefix: String, restParser: RestPropMapper<*,*>? = null) : Iterable {","During the previous review I slightly rewrite this and something else, I hope this will be useful. +https://github.com/JetBrains/kotlin/commit/ef2ea84a85c3415fc9fa1c933e44c880df979d80#diff-4ff40116c0033e709c32c7abef5b2b0eR84 +",2015-08-31 12:24:57 +810,"@@ -0,0 +1,32 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType ++import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType ++import javax.lang.model.type.TypeMirror ++ ++class SymbolBasedPrimitiveType(typeMirror: T,",Drop generic type parameter here and inherit from `SymbolBasedType<*>`,2017-04-25 12:27:41 +806,"@@ -0,0 +1,32 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType ++import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType ++import javax.lang.model.type.TypeMirror ++ ++class SymbolBasedPrimitiveType(typeMirror: T, ++ javac: JavacWrapper) : SymbolBasedType(typeMirror, javac), JavaPrimitiveType { ++ ++ override val type ++ get() = with(typeMirror.toString()) { ++ if (""void"" == this) null else JvmPrimitiveType.get(this).primitiveType",Please inspect `TypeMirror.getKind` instead of `toString`,2017-04-25 12:20:25 +831,"@@ -0,0 +1,32 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType ++import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType ++ ++class TreeBasedPrimitiveType(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedType(tree, treePath, javac), JavaPrimitiveType { ++ ++ override val type ++ get() = if (""void"" == tree.toString()) null else JvmPrimitiveType.get(tree.toString()).primitiveType","Again, please inspect `tree.getKind()` instead of the string returned by `toString`",2017-04-25 16:34:26 +78,"@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class SpecifySuperExplicitlyFix extends JetIntentionAction {","About functionality: +1. It's not good to give a user a partial functionality. +He would be surprised to find that the case 'super.foo()' is working, but 'super.foo().bar()' isn't. +2. I'd expect some choice which receiver I'd like to invoke here. +",2013-05-29 11:07:40 +79,"@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class SpecifySuperExplicitlyFix extends JetIntentionAction { ++ private PsiElement elementToReplace; ++ private final LinkedHashSet options;","It's better to use less concrete types like Set or Collection here. (The following code should be independent of concrete implementation of collection to make it easy to change it later if necessary). +",2013-05-29 11:09:34 +82,"@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class SpecifySuperExplicitlyFix extends JetIntentionAction { ++ private PsiElement elementToReplace; ++ private final LinkedHashSet options; ++ ++ ++ public SpecifySuperExplicitlyFix(@NotNull JetSuperExpression element, @NotNull LinkedHashSet options) { ++ super(element); ++ elementToReplace = element; ++ this.options = options; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""specify.super.explicitly""); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""specify.super.explicitly.family""); ++ } ++ ++ @Override ++ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { ++ return !options.isEmpty(); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) {","Don't override 'Deprecated' method. +",2013-05-29 11:15:42 +80,"@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class SpecifySuperExplicitlyFix extends JetIntentionAction { ++ private PsiElement elementToReplace; ++ private final LinkedHashSet options; ++ ++ ++ public SpecifySuperExplicitlyFix(@NotNull JetSuperExpression element, @NotNull LinkedHashSet options) { ++ super(element); ++ elementToReplace = element; ++ this.options = options; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""specify.super.explicitly""); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""specify.super.explicitly.family""); ++ } ++ ++ @Override ++ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { ++ return !options.isEmpty(); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) { ++ elementToReplace = elementToReplace.replace(JetPsiFactory.createExpression(project, options.iterator().next())); ++ buildAndShowTemplate(project, editor, file, elementToReplace, options); ++ } ++ ++ public static JetIntentionActionFactory createFactory() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) {","I'd rather divide this method into several smaller ones with meaningful names. +",2013-05-29 11:10:46 +81,"@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class SpecifySuperExplicitlyFix extends JetIntentionAction { ++ private PsiElement elementToReplace; ++ private final LinkedHashSet options; ++ ++ ++ public SpecifySuperExplicitlyFix(@NotNull JetSuperExpression element, @NotNull LinkedHashSet options) { ++ super(element); ++ elementToReplace = element; ++ this.options = options; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""specify.super.explicitly""); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""specify.super.explicitly.family""); ++ } ++ ++ @Override ++ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { ++ return !options.isEmpty(); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) { ++ elementToReplace = elementToReplace.replace(JetPsiFactory.createExpression(project, options.iterator().next())); ++ buildAndShowTemplate(project, editor, file, elementToReplace, options); ++ } ++ ++ public static JetIntentionActionFactory createFactory() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetSuperExpression superExp = QuickFixUtil.getParentElementOfType(diagnostic, JetSuperExpression.class); ++ if (superExp == null) { ++ return null; ++ } ++ ++ JetClass klass = QuickFixUtil.getParentElementOfType(diagnostic, JetClass.class); ++ if (klass == null) { ++ return null; ++ } ++ ++ JetDelegationSpecifierList superClasses = PsiTreeUtil.getChildOfType(klass, JetDelegationSpecifierList.class); ++ if (superClasses == null) { ++ return null; ++ } ++ ++ //Used for checking visibility ++ BindingContext contextClasses = KotlinCacheManagerUtil.getDeclarationsFromProject(superExp).getBindingContext(); ++ ClassDescriptor fromClass = contextClasses.get(BindingContext.CLASS, klass); ++ if (fromClass == null) { ++ return null; ++ } ++ ++ //Fetch class descriptors for all super classes ++ LinkedHashSet superClassDescs = new LinkedHashSet(); ++ for (JetDelegationSpecifier delSpec : superClasses.getDelegationSpecifiers()) { ++ JetSimpleNameExpression jetRef = PsiTreeUtil.findChildOfType(delSpec.getTypeReference(), JetSimpleNameExpression.class); ++ if (jetRef == null) { ++ continue; ++ } ++ ClassDescriptor classDesc = resolveToClass(jetRef, contextClasses); ++ if (classDesc != null) { ++ superClassDescs.add(classDesc); ++ } ++ } ++ if (superClassDescs.isEmpty()) { ++ return null; ++ } ++ ++ //Get the name of the member in question and other access information. The super expression ++ //MUST be a part of a dot qualified expression. ++ JetDotQualifiedExpression dotExp = QuickFixUtil.getParentElementOfType(diagnostic, JetDotQualifiedExpression.class); ++ if (dotExp == null) { ++ return null; ++ } ++ JetExpression nextExp = dotExp; ++ JetExpression currentExp = null; ++ ++ ArrayList memberNames = new ArrayList(); ++ //contains a null in the index where the memberName at that same index is of a property. ++ ArrayList argsForFunction = new ArrayList(); ++ while (nextExp != null && (nextExp instanceof JetDotQualifiedExpression || nextExp instanceof JetArrayAccessExpression)) { ++ currentExp = nextExp; ++ String memberName; ++ JetValueArgumentList valArgs; ++ ++ if (currentExp instanceof JetDotQualifiedExpression) { ++ JetCallExpression call = PsiTreeUtil.getChildOfType(currentExp, JetCallExpression.class); ++ if (call != null) { ++ JetSimpleNameExpression name = PsiTreeUtil.getChildOfType(call, JetSimpleNameExpression.class); ++ if (name == null) { ++ return null; ++ } ++ memberName = name.getText(); ++ valArgs = call.getValueArgumentList(); ++ } ++ else { ++ JetSimpleNameExpression name = PsiTreeUtil.getChildOfType(currentExp, JetSimpleNameExpression.class); ++ if (name == null) { ++ return null; ++ } ++ memberName = name.getText(); ++ valArgs = null; ++ } ++ } ++ else { ++ //array indexing not supported for now. ++ return null; ++ /** ++ memberName = ""get""; //array indexing is the same as get function call ++ ++ JetContainerNode indexNode = ((JetArrayAccessExpression) currentExp).getIndicesNode(); ++ JetConstantExpression constant = PsiTreeUtil.getChildOfType(indexNode, JetConstantExpression.class); ++ JetReferenceExpression refIndex = PsiTreeUtil.getChildOfType(indexNode, JetReferenceExpression.class); ++ if (constant == null && refIndex == null) { ++ return null; ++ } ++ if (constant != null) { ++ valArgs = JetPsiFactory.createCallArguments(diagnostic.getPsiFile() ++ .getProject(), ""("" + constant.getText() + "")""); ++ } ++ else { ++ valArgs = JetPsiFactory.createCallArguments(diagnostic.getPsiFile() ++ .getProject(), ""("" + refIndex.getText() + "")""); ++ }**/ ++ } ++ memberNames.add(memberName); ++ argsForFunction.add(valArgs); ++ nextExp = PsiTreeUtil.getParentOfType(currentExp, JetExpression.class); ++ } ++ if (memberNames.isEmpty()) { ++ return null; ++ } ++ ++ //Right now, code has unexpected behavior with chained calls e.g. super.foo().bar.baz() so we just return null. ++ if (memberNames.size() > 1) { ++ return null; ++ } ++ ++ ++ //Get the expected type of the expression if applicable (e.g. var a : Int = super.foo) ++ BindingContext contextExpressions = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) diagnostic.getPsiFile()) ++ .getBindingContext(); ++ JetProperty assignment = PsiTreeUtil.getParentOfType(currentExp, JetProperty.class); ++ JetType expectedJetType = null; ++ if (assignment != null) { ++ expectedJetType = contextExpressions.get(BindingContext.TYPE, assignment.getTypeRef()); ++ } ++ //TODO with Expected Type, if it is part of a return statement, look at return type of the function. ++ ++ LinkedHashSet options = new LinkedHashSet(); ++ for (ClassDescriptor classDesc : superClassDescs) { ++ //ClassDescriptor currentClassDesc = classDesc; ++ ++ boolean failed = false; ++ JetType returnType; ++ //for (int i = 0; i < memberNames.size(); i++) { ++ //should be currentClassDesc and .get(i)'s ++ returnType = memberNameAndArgsFound(classDesc, fromClass, memberNames.get(0), ++ argsForFunction.get(0), contextExpressions); ++ /* ++ if (returnType == null) { ++ failed = true; ++ break; ++ } ++ //Update the class from which we see the next member. ++ fromClass = currentClassDesc; ++ TODO deal with generic types (especially in arrays) as the return type. ++ currentClassDesc = DescriptorUtils.getClassDescriptorForType(returnType); ++ }*/ ++ if (!failed && returnType != null && ++ (expectedJetType == null || JetTypeChecker.INSTANCE.isSubtypeOf(returnType, expectedJetType))) { ++ options.add(""super<"" + classDesc.getName().getIdentifier() + "">""); ++ } ++ } ++ return new SpecifySuperExplicitlyFix(superExp, options); ++ } ++ }; ++ } ++ ++ /*returns null if false or error occured*/ ++ private static JetType memberNameAndArgsFound(@NotNull ClassDescriptor classDesc, @NotNull ClassDescriptor fromClass,","Please annotate return type as Nullable if a method may return null. +The method name should explain what this method does (better using some verbs like 'do something') and what it returns ('memberNameAndArgsFound' returning JetType is unclear). +",2013-05-29 11:13:58 +83,"@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.codeInsight.template.*; ++import com.intellij.openapi.editor.CaretModel; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.util.PsiTreeUtil; ++import com.intellij.refactoring.rename.inplace.MyLookupExpression; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.descriptors.*; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.lang.resolve.BindingContext; ++import org.jetbrains.jet.lang.resolve.name.Name; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.lang.types.checker.JetTypeChecker; ++import org.jetbrains.jet.plugin.JetBundle; ++import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import java.util.List; ++ ++public class SpecifySuperExplicitlyFix extends JetIntentionAction { ++ private PsiElement elementToReplace; ++ private final LinkedHashSet options; ++ ++ ++ public SpecifySuperExplicitlyFix(@NotNull JetSuperExpression element, @NotNull LinkedHashSet options) { ++ super(element); ++ elementToReplace = element; ++ this.options = options; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""specify.super.explicitly""); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""specify.super.explicitly.family""); ++ } ++ ++ @Override ++ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { ++ return !options.isEmpty(); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) { ++ elementToReplace = elementToReplace.replace(JetPsiFactory.createExpression(project, options.iterator().next())); ++ buildAndShowTemplate(project, editor, file, elementToReplace, options); ++ } ++ ++ public static JetIntentionActionFactory createFactory() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetSuperExpression superExp = QuickFixUtil.getParentElementOfType(diagnostic, JetSuperExpression.class); ++ if (superExp == null) { ++ return null; ++ } ++ ++ JetClass klass = QuickFixUtil.getParentElementOfType(diagnostic, JetClass.class); ++ if (klass == null) { ++ return null; ++ } ++ ++ JetDelegationSpecifierList superClasses = PsiTreeUtil.getChildOfType(klass, JetDelegationSpecifierList.class); ++ if (superClasses == null) { ++ return null; ++ } ++ ++ //Used for checking visibility ++ BindingContext contextClasses = KotlinCacheManagerUtil.getDeclarationsFromProject(superExp).getBindingContext(); ++ ClassDescriptor fromClass = contextClasses.get(BindingContext.CLASS, klass); ++ if (fromClass == null) { ++ return null; ++ } ++ ++ //Fetch class descriptors for all super classes ++ LinkedHashSet superClassDescs = new LinkedHashSet(); ++ for (JetDelegationSpecifier delSpec : superClasses.getDelegationSpecifiers()) { ++ JetSimpleNameExpression jetRef = PsiTreeUtil.findChildOfType(delSpec.getTypeReference(), JetSimpleNameExpression.class); ++ if (jetRef == null) { ++ continue; ++ } ++ ClassDescriptor classDesc = resolveToClass(jetRef, contextClasses); ++ if (classDesc != null) { ++ superClassDescs.add(classDesc); ++ } ++ } ++ if (superClassDescs.isEmpty()) { ++ return null; ++ } ++ ++ //Get the name of the member in question and other access information. The super expression ++ //MUST be a part of a dot qualified expression. ++ JetDotQualifiedExpression dotExp = QuickFixUtil.getParentElementOfType(diagnostic, JetDotQualifiedExpression.class); ++ if (dotExp == null) { ++ return null; ++ } ++ JetExpression nextExp = dotExp; ++ JetExpression currentExp = null; ++ ++ ArrayList memberNames = new ArrayList(); ++ //contains a null in the index where the memberName at that same index is of a property. ++ ArrayList argsForFunction = new ArrayList(); ++ while (nextExp != null && (nextExp instanceof JetDotQualifiedExpression || nextExp instanceof JetArrayAccessExpression)) { ++ currentExp = nextExp; ++ String memberName; ++ JetValueArgumentList valArgs; ++ ++ if (currentExp instanceof JetDotQualifiedExpression) { ++ JetCallExpression call = PsiTreeUtil.getChildOfType(currentExp, JetCallExpression.class); ++ if (call != null) { ++ JetSimpleNameExpression name = PsiTreeUtil.getChildOfType(call, JetSimpleNameExpression.class); ++ if (name == null) { ++ return null; ++ } ++ memberName = name.getText(); ++ valArgs = call.getValueArgumentList(); ++ } ++ else { ++ JetSimpleNameExpression name = PsiTreeUtil.getChildOfType(currentExp, JetSimpleNameExpression.class); ++ if (name == null) { ++ return null; ++ } ++ memberName = name.getText(); ++ valArgs = null; ++ } ++ } ++ else { ++ //array indexing not supported for now. ++ return null; ++ /** ++ memberName = ""get""; //array indexing is the same as get function call ++ ++ JetContainerNode indexNode = ((JetArrayAccessExpression) currentExp).getIndicesNode(); ++ JetConstantExpression constant = PsiTreeUtil.getChildOfType(indexNode, JetConstantExpression.class); ++ JetReferenceExpression refIndex = PsiTreeUtil.getChildOfType(indexNode, JetReferenceExpression.class); ++ if (constant == null && refIndex == null) { ++ return null; ++ } ++ if (constant != null) { ++ valArgs = JetPsiFactory.createCallArguments(diagnostic.getPsiFile() ++ .getProject(), ""("" + constant.getText() + "")""); ++ } ++ else { ++ valArgs = JetPsiFactory.createCallArguments(diagnostic.getPsiFile() ++ .getProject(), ""("" + refIndex.getText() + "")""); ++ }**/ ++ } ++ memberNames.add(memberName); ++ argsForFunction.add(valArgs); ++ nextExp = PsiTreeUtil.getParentOfType(currentExp, JetExpression.class); ++ } ++ if (memberNames.isEmpty()) { ++ return null; ++ } ++ ++ //Right now, code has unexpected behavior with chained calls e.g. super.foo().bar.baz() so we just return null. ++ if (memberNames.size() > 1) { ++ return null; ++ } ++ ++ ++ //Get the expected type of the expression if applicable (e.g. var a : Int = super.foo) ++ BindingContext contextExpressions = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) diagnostic.getPsiFile()) ++ .getBindingContext(); ++ JetProperty assignment = PsiTreeUtil.getParentOfType(currentExp, JetProperty.class); ++ JetType expectedJetType = null; ++ if (assignment != null) { ++ expectedJetType = contextExpressions.get(BindingContext.TYPE, assignment.getTypeRef()); ++ } ++ //TODO with Expected Type, if it is part of a return statement, look at return type of the function. ++ ++ LinkedHashSet options = new LinkedHashSet(); ++ for (ClassDescriptor classDesc : superClassDescs) { ++ //ClassDescriptor currentClassDesc = classDesc; ++ ++ boolean failed = false; ++ JetType returnType; ++ //for (int i = 0; i < memberNames.size(); i++) { ++ //should be currentClassDesc and .get(i)'s ++ returnType = memberNameAndArgsFound(classDesc, fromClass, memberNames.get(0), ++ argsForFunction.get(0), contextExpressions); ++ /* ++ if (returnType == null) { ++ failed = true; ++ break; ++ } ++ //Update the class from which we see the next member. ++ fromClass = currentClassDesc; ++ TODO deal with generic types (especially in arrays) as the return type. ++ currentClassDesc = DescriptorUtils.getClassDescriptorForType(returnType); ++ }*/ ++ if (!failed && returnType != null && ++ (expectedJetType == null || JetTypeChecker.INSTANCE.isSubtypeOf(returnType, expectedJetType))) { ++ options.add(""super<"" + classDesc.getName().getIdentifier() + "">""); ++ } ++ } ++ return new SpecifySuperExplicitlyFix(superExp, options); ++ } ++ }; ++ } ++ ++ /*returns null if false or error occured*/ ++ private static JetType memberNameAndArgsFound(@NotNull ClassDescriptor classDesc, @NotNull ClassDescriptor fromClass, ++ @NotNull String memberName, ++ @Nullable JetValueArgumentList valArgs, @NotNull BindingContext contextExpressions) { ++ if (valArgs == null) { ++ Collection varDescs = classDesc.getMemberScope(classDesc.getDefaultType().getArguments()) ++ .getProperties(Name.identifier(memberName)); ++ return memberNamePropFound(classDesc, fromClass, varDescs); ++ } ++ else { ++ Collection funDescs = classDesc.getMemberScope(classDesc.getDefaultType().getArguments()) ++ .getFunctions(Name.identifier(memberName)); ++ return memberNameFuncFound(fromClass, funDescs, valArgs, contextExpressions); ++ ++ } ++ } ++ ++ private static JetType memberNameFuncFound(@NotNull ClassDescriptor fromClass, ++ @NotNull Collection funDescs, ++ @NotNull JetValueArgumentList valArgs, @NotNull BindingContext contextExpressions) { ++ for (FunctionDescriptor fun : funDescs) { ++ if (fun.getModality() == Modality.ABSTRACT || !fun.getKind().isReal() || ++ !Visibilities.isVisible(fun, fromClass)) { ++ continue; ++ } ++ List valParams = fun.getValueParameters(); ++ List jValArgs = valArgs.getArguments(); ++ if (jValArgs.size() != valParams.size()) { ++ continue; ++ } ++ boolean argTypesMatch = true; ++ for (int j = 0; j < valParams.size(); j++) { ++ JetExpression expr = jValArgs.get(j).getArgumentExpression(); ++ JetType subtype = contextExpressions.get(BindingContext.EXPRESSION_TYPE, expr); ++ if (subtype == null || !JetTypeChecker.INSTANCE.isSubtypeOf(subtype, valParams.get(j).getType())) { ++ argTypesMatch = false; ++ break; ++ } ++ } ++ if (!argTypesMatch) { ++ continue; ++ } ++ return fun.getReturnType(); ++ } ++ return null; ++ } ++ ++ private static JetType memberNamePropFound(@NotNull ClassDescriptor classDesc, @NotNull ClassDescriptor fromClass, ++ @NotNull Collection varDescs) { ++ for (VariableDescriptor var : varDescs) { ++ if (classDesc.getKind() != ClassKind.TRAIT && Visibilities.isVisible(var, fromClass)) { ++ return var.getType(); ++ } ++ } ++ return null; ++ } ++ ++ /*Taken and modified from MapPlatformClassToKotlinFix*/","You shouldn't copy code. You may change this method in its class or/and move it to util instead. +",2013-05-29 11:17:36 +366,"@@ -0,0 +1,34 @@ ++# Class Literals as Annotation Arguments ++ ++Prior to M12 Kotlin annotation allowed parameters of type `java.lang.Class<...>` whose values could be of the form `javaClass<...>()`. ++Since M12 both these options are deprecated, and subject to deletion in further milestones. ++ ++## Annotation Parameters ++ ++Annotation parameters of type `java.lang.Class` are deprecated. ++ ++Annotation parameters of type `kotlin.reflect.KClass` are supported. ++ ++A quick-fix transforming one into the other is provided. ++ ++## Annotation Arguments ++ ++Arguments of the form `javaClass()` are deprecated. ++ ++Arguments of teh form `ClassName::class` are supported.","teh -> the +",2015-04-04 23:01:08 +367,"@@ -0,0 +1,34 @@ ++# Class Literals as Annotation Arguments ++ ++Prior to M12 Kotlin annotation allowed parameters of type `java.lang.Class<...>` whose values could be of the form `javaClass<...>()`. ++Since M12 both these options are deprecated, and subject to deletion in further milestones. ++ ++## Annotation Parameters ++ ++Annotation parameters of type `java.lang.Class` are deprecated. ++ ++Annotation parameters of type `kotlin.reflect.KClass` are supported. ++ ++A quick-fix transforming one into the other is provided. ++ ++## Annotation Arguments ++ ++Arguments of the form `javaClass()` are deprecated. ++ ++Arguments of teh form `ClassName::class` are supported. ++ ++A quick-fix transforming one into the other is provided. ++ ++## Loading Annotation Classes from Java ++ ++Java annotation `@interfaces` may declare methods of type `java.lang.Class`. And on the JVM this is the only representation we can compile our annotations to. These should be processed specially and mapped to `kotlin.reflect.KClass`. At the call sites for annotations delcared in Kotlin as well as in Java, when a property of type `KClass` is accessed, we have to map its value from `java.lang.Class` to `kotlin.reflect.KClass`. Same needs to happen when we access those properties through reflection.","delcared -> declared +",2015-04-04 23:03:41 +368,"@@ -0,0 +1,34 @@ ++# Class Literals as Annotation Arguments ++ ++Prior to M12 Kotlin annotation allowed parameters of type `java.lang.Class<...>` whose values could be of the form `javaClass<...>()`. ++Since M12 both these options are deprecated, and subject to deletion in further milestones. ++ ++## Annotation Parameters ++ ++Annotation parameters of type `java.lang.Class` are deprecated. ++ ++Annotation parameters of type `kotlin.reflect.KClass` are supported. ++ ++A quick-fix transforming one into the other is provided. ++ ++## Annotation Arguments ++ ++Arguments of the form `javaClass()` are deprecated. ++ ++Arguments of teh form `ClassName::class` are supported. ++ ++A quick-fix transforming one into the other is provided. ++ ++## Loading Annotation Classes from Java ++ ++Java annotation `@interfaces` may declare methods of type `java.lang.Class`. And on the JVM this is the only representation we can compile our annotations to. These should be processed specially and mapped to `kotlin.reflect.KClass`. At the call sites for annotations delcared in Kotlin as well as in Java, when a property of type `KClass` is accessed, we have to map its value from `java.lang.Class` to `kotlin.reflect.KClass`. Same needs to happen when we access those properties through reflection. ++ ++> This is unprecedented in Kotlin: never before we mapped a Java class to another *real* class, all mappings we had before were fictitious, e.g. existed at compile time only. ++ ++Since it is likely to be rather common that the value of an annotation property will only be used to retrieve an instance of `java.lang.Class`, e.g. `annInstance.implClass.java`, to avoid runtime overhead, we should optimize such cases in the JVM back-end by skipping the steps of converting a `java.lamg.Class` to `KClass` and then back. ++","lamg -> lang +",2015-04-04 23:05:23 +634,"@@ -0,0 +1,34 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.codeInspection.CleanupLocalInspectionTool ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection ++import org.jetbrains.kotlin.psi.KtClassBody ++ ++class RemoveEmptyClassBodyInspection : IntentionBasedInspection(RemoveEmptyClassBodyIntention::class), CleanupLocalInspectionTool {","If you want your inspection to run as part of code cleanup, you need to specify cleanupTool=""true"" in its XML registration. +",2016-10-10 11:06:19 +990,"@@ -0,0 +1,34 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.adapters ++ ++import org.jetbrains.kotlin.effectsystem.structure.ConstantID ++import org.jetbrains.kotlin.effectsystem.structure.ESValueID ++import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue ++ ++class DataFlowValueID(val dfv: DataFlowValue) : ESValueID {",Not quite sure this wrapper is needed. Can `DataFlowValue` itself serve you here?,2017-08-15 17:06:51 +800,"@@ -0,0 +1,34 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.TypeParameterElement ++import javax.lang.model.type.TypeVariable ++ ++class SymbolBasedTypeParameter(element: T, ++ javac: JavacWrapper) : SymbolBasedClassifier(element, javac), JavaTypeParameter { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(element.simpleName.toString())",`Name.identifier`,2017-04-25 11:56:09 +801,"@@ -0,0 +1,34 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.TypeParameterElement ++import javax.lang.model.type.TypeVariable ++ ++class SymbolBasedTypeParameter(element: T, ++ javac: JavacWrapper) : SymbolBasedClassifier(element, javac), JavaTypeParameter { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(element.simpleName.toString()) ++ ++ override val upperBounds ++ get() = listOf(SymbolBasedClassifierType((element.asType() as TypeVariable).upperBound, javac))",I think you should handle the case of `IntersectionType` here by expanding it into multiple bounds. `TypeVariable.getUpperBound`'s javadoc implies that this is possible here.,2017-04-25 12:04:14 +373,"@@ -0,0 +1,342 @@ ++# Function Types in Kotlin on JVM ++ ++## Goals ++ ++* Get rid of 23 hardwired physical function classes. The problem with them is, ++reflection introduces a few kinds of functions but each of them should be invokable as a normal function as well, and so ++we get `{top-level, member, extension, member-extension, local, ...} * 23` = **a lot** of physical classes in the runtime. ++* Make extension functions coercible to normal functions (with an extra parameter). ++At the moment it's not possible to do `listOfStrings.map(String::length)` ++* Allow functions with more than 23 parameters, theoretically any number of parameters (in practice 255 on JVM). ++* At the same time, allow to implement Kotlin functions easily from Java: `new Function2() { ... }` and overriding `invoke` only would be the best. ++Enabling SAM conversions on Java 8 would also be terrific. ++ ++## Brief solution overview ++ ++* Treat extension functions almost like non-extension functions with one extra parameter, allowing to use them almost interchangeably. ++* Introduce a physical class `Function` and unlimited number of *fictitious* (synthetic) classes `Function0`, `Function1`, ... in the compiler front-end ++* On JVM, introduce `Function0`..`Function22`, which are optimized in a certain way, ++and `FunctionN` for functions with 23+ parameters. ++When passing a lambda to Kotlin from Java, one will need to implement one of these interfaces. ++* Also on JVM (under the hood) add abstract `FunctionImpl` which implements all of `Fun0`..`Fun22` and `FunN` ++(throwing exceptions), and which knows its arity. ++Kotlin lambdas are translated to subclasses of this abstract class, passing the correct arity to the super constructor. ++* Provide a way to get arity of an arbitrary `Function` object (pretty straightforward). ++* Hack `is/as Function5` on any numbered function in codegen (and probably `KClass.cast()` in reflection) to check against `Function` and its arity. ++ ++## Extension functions ++ ++Extension function type `T.(P) -> R` is now just a shorthand for `[kotlin.extension] Function2`. ++`kotlin.extension` is a **type annotation** defined in built-ins. ++So effectively functions and extension functions now have the same type, ++how can we make extension function expressions support extension function call syntax? ++ ++We introduce the following convention: expression `foo` of type `Foo` can be used as an extension function ++(i.e. `object.foo(arguments)`) if and only if there is a function `invokeExtension` ++with the corresponding parameters available on the type `Foo`. ++This function may be declared in class `Foo` or somewhere as an extension to `Foo`. ++ ++> Note that at the moment a less convenient convention is used: there must be a **member extension** ++> function `invoke` in the class which you want to be used as an extension function. ++> This means you can't add ""extension-function-ness"" to a foreign class, ++> since you'd need to declare a function with two receivers. ++> The new approach will solve this problem. ++ ++We declare `invokeExtension` to be available on all extension functions: ++ ++``` kotlin ++package kotlin ++ ++... ++fun (T.() -> R).invokeExtension(): R = this() ++fun (T.(P1) -> R).invokeExtension(p1: P1): R = this(p1) ++... ++``` ++ ++So now an expression type-checked to an ""extension function type"" can be used with the desired syntax. ++But, since a function type and a corresponding extension function type effectively have the same classifier (e.g. `Function7`), ++they are coercible to each other and therefore our `invokeExtension` will be applicable to the usual ++functions as well, which is something we don't want to happen! Example: ++ ++``` kotlin ++val lengthHacked: (String) -> Int = { it.length } ++ ++fun test() = """".lengthHacked() // <-- bad! The declared function accepts a single non-receiver argument ++ // and is not designed to be invoked as an extension ++``` ++ ++And here we introduce the following **restriction**: given a call `object.foo(arguments)`, ++if `foo` is resolved **exactly** to the built-in extension function `invokeExtension`, ++then the call *will not compile* unless the receiver type is annotated with `[extension]`. ++So `invokeExtension` will yield an error when used on a normal (not extension) function. ++ ++To make your class invokable as an extension you only need to declare `invokeExtension`. ++Declaring `invoke` (and maybe overriding it from the needed function class) will only make your class invokable *as a usual function*. ++Inheriting from a function type thus makes sense if you want your class to behave like a simple function. ++Inheriting from an extension function type however makes no sense and should be prohibited / frowned upon. ++In a broad sense, providing type annotations on supertypes (which is what inheriting from an extension function is) ++maybe should be diagnosed in the compiler (maybe not, more knowledge needed). ++ ++With this we'll get rid of classes `ExtensionFunction0`, `ExtensionFunction1`, ... ++and the rest of this article will deal only with usual functions. ++ ++## Function0, Function1, ... types ++ ++The arity of the functional trait that the type checker can create in theory **is not limited** to any number, ++but in practice should be limited to 255 on JVM. ++ ++These traits are named `kotlin.Function0`, `kotlin.Function1`, ..., `kotlin.Function42`, ... ++They are *fictitious*, which means they have no sources and no runtime representation. ++Type checker creates the corresponding descriptors on demand, IDE creates corresponding source files on demand as well. ++Each of them inherits from `kotlin.Function` (described below) and contains a single ++`fun invoke()` with the corresponding number of parameters and return type. ++ ++> TODO: investigate exactly what changes in IDE should be done and if they are possible at all. ++ ++On JVM function types are erased to the physical classes defined in package `kotlin.jvm.internal`: ++`Function0`, `Function1`, ..., `Function22` and `FunctionN` for 23+ parameters. ++ ++## Function trait ++ ++There's also an empty trait `kotlin.Function` for cases when e.g. you're storing functions with different/unknown arity ++in a collection to invoke them reflectively somewhere else. ++ ++``` kotlin ++package kotlin ++ ++trait Function ++``` ++ ++It's a physical trait, declared in platform-agnostic built-ins, and present in `kotlin-runtime.jar` for example. ++However its declaration is **empty** and should be empty because every physical JVM function class `Function0`, `Function1`, ... ++inherits from it (and adds `invoke()`), and we don't want to override anything besides `invoke()` when doing it from Java code. ++ ++## Functions with 0..22 parameters at runtime ++ ++There are 23 function traits in `kotlin.platform.jvm`: `Function0`, `Function1`, ..., `Function22`. ++Here's `Function1` declaration, for example: ++ ++``` kotlin ++package kotlin.platform.jvm ++ ++trait Function1 : kotlin.Function { ++ fun invoke(p1: P1): R ++} ++``` ++ ++These traits are supposed to be inherited from by Java classes when passing lambdas to Kotlin. ++ ++Package `kotlin.platform.jvm` is supposed to contain interfaces which help use Kotlin from Java. ++(And not from Kotlin, because normally you would use a function type there, ++most of the time even without mentioning built-in function classes: `(P1, P2, P3) -> R`.) ++ ++## Translation of Kotlin lambdas ++ ++There's also `FunctionImpl` abstract class at runtime which helps in implementing `arity` and vararg-invocation. ++It inherits from all the physical function classes, unfortunately (more on that later). ++ ++``` kotlin ++package kotlin.jvm.internal ++ ++abstract class FunctionImpl(override val arity: Int) : ++ Function, ++ Function0, Function1, ..., ..., Function22<...>, ++ FunctionN // See the next section on FunctionN ++{ ++ override fun invoke(): Any? { ++ // Default implementations of all ""invoke""s invoke ""invokeVararg"" ++ // This is needed for KFunctionImpl (see below) ++ assert(arity == 0) ++ return invokeVararg() ++ } ++ ++ override fun invoke(p1: Any?): Any? { ++ assert(arity == 1) ++ return invokeVararg(p1) ++ } ++ ++ ... ++ override fun invoke(p1: Any?, ..., p22: Any?) { ... } ++ ++ override fun invokeVararg(vararg p: Any?): Any? = throw UnsupportedOperationException() ++ ++ override fun toString() = ... // Some calculation involving generic runtime signatures ++} ++``` ++ ++> TODO: sadly, this class needs to be implemented in Java because supertypes need to be **raw** classes ++> for reflection to pick up correct generic signatures for inheritors ++ ++Each lambda is compiled to an anonymous class which inherits from `FunctionImpl` and implements the corresponding `invoke`: ++ ++``` kotlin ++{ (s: String): Int -> s.length } ++ ++// is translated to ++ ++object : FunctionImpl(2), Function2 {","Doesn't `Function2` have 3 type parameters (2 for parameter types and 1 for return type)? +",2015-04-08 16:13:34 +723,"@@ -0,0 +1,35 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClassifierType ++import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter ++import org.jetbrains.kotlin.name.SpecialNames ++import javax.lang.model.element.TypeParameterElement ++import javax.lang.model.type.TypeVariable ++ ++class JavacTypeParameter(element: T, ++ javac: Javac) : JavacClassifier(element, javac), JavaTypeParameter { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(element.simpleName.toString()) ++ ++ override val upperBounds: Collection ++ get() = listOf(JavacClassifierType((element.asType() as TypeVariable).upperBound, javac)) ++","In NB plugin, `equals` & `hashCode` are also implemented for this class. Should we have them here?",2017-04-05 15:17:27 +978,"@@ -0,0 +1,36 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.structure ++ ++/** ++ * An abstraction of effect-generating nature of some operation. ++ * ++ * [ESFunctor] roughly corresponds to some call, but it cares only ++ * about effects of this call, so instead of value arguments, its [apply] ++ * method takes just description of effects of each argument ++ * (represented by [EffectSchema]), and produces effects of the whole call ++ * (instead of some value, compared to usual calls). ++ * ++ * Implementors should never produce non-conservative effects. ++ * However, they are not obliged to produce most precise description ++ * of effects, though they are encouraged to do so. ++ */ ++ ++interface ESFunctor {",May be it's better to move this into `functors` package,2017-08-15 16:27:05 +724,"@@ -0,0 +1,36 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaWildcardType ++import javax.lang.model.type.TypeMirror ++import javax.lang.model.type.WildcardType ++ ++class JavacWildcardType(typeMirror: T, ++ javac: Javac) : JavacType(typeMirror, javac), JavaWildcardType { ++ ++ override val bound ++ get() = typeMirror.let { ++ val boundMirror = (it as WildcardType).extendsBound ?: it.superBound ++ ++ if (boundMirror != null) create(boundMirror, javac) else null","`boundMirror.let { create(it, javac) }`",2017-04-05 15:18:45 +808,"@@ -0,0 +1,36 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaWildcardType ++import javax.lang.model.type.TypeMirror ++import javax.lang.model.type.WildcardType ++ ++class SymbolBasedWildcardType(typeMirror: T,",Looks like generic type parameter `T` is not needed here as well. This class should just inherit from `SymbolBasedType` and `typeMirror` should have the type `WildcardType`,2017-04-25 12:25:51 +797,"@@ -0,0 +1,38 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.AnnotationMirror ++import javax.lang.model.element.TypeElement ++ ++open class SymbolBasedAnnotation(val annotationMirror: AnnotationMirror, ++ val javac: JavacWrapper) : JavaElement, JavaAnnotation { ++ ++ override val arguments ++ get() = annotationMirror.elementValues ++ .map { SymbolBasedAnnotationArgument.create(it.value.value, Name.identifier(it.key.simpleName.toString()), javac) }","`.map { (key, value) -> ... }`",2017-04-25 11:47:36 +815,"@@ -0,0 +1,39 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.sun.tools.javac.util.Options ++import java.util.regex.Pattern ++ ++object JavacOptionsMapper { ++ ++ fun map(options: Options, arguments: List) = arguments.forEach { options.putOption(it) }","Please don't use expression body syntax for `Unit`-returning functions, it's slightly confusing (I was figuring out what does this function return)",2017-04-25 12:57:47 +814,"@@ -0,0 +1,39 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.sun.tools.javac.util.Options ++import java.util.regex.Pattern ++ ++object JavacOptionsMapper { ++ ++ fun map(options: Options, arguments: List) = arguments.forEach { options.putOption(it) } ++ ++ private val optionPattern by lazy { Pattern.compile(""\\s+"") }",There's no need to make it lazy (it will be accessed anyway any time `JavacOptionsMapper.map` is called),2017-04-25 12:55:59 +816,"@@ -0,0 +1,39 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.sun.tools.javac.util.Options ++import java.util.regex.Pattern ++ ++object JavacOptionsMapper { ++ ++ fun map(options: Options, arguments: List) = arguments.forEach { options.putOption(it) } ++ ++ private val optionPattern by lazy { Pattern.compile(""\\s+"") } ++ ++ private fun Options.putOption(option: String) = option ++ .split(optionPattern) ++ .filter { it.isNotEmpty() } ++ .let { arg -> ++ when(arg.size) { ++ 1 -> put(arg[0], arg[0]) ++ 2 -> put(arg[0], arg[1]) ++ else -> null","`else -> null` is not needed here, I think",2017-04-25 12:58:02 +796,"@@ -0,0 +1,39 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner ++import org.jetbrains.kotlin.load.java.structure.JavaClassifier ++import org.jetbrains.kotlin.name.FqName ++import javax.lang.model.element.Element ++ ++abstract class SymbolBasedClassifier(element: T, ++ javac: JavacWrapper) : SymbolBasedElement(element, javac), JavaClassifier, JavaAnnotationOwner { ++ ++ override val annotations ++ get() = element.annotationMirrors ++ .map { SymbolBasedAnnotation(it, javac) } ++ ++ override fun findAnnotation(fqName: FqName) = element.annotationMirrors ++ .find { it.toString() == ""@${fqName.asString()}"" }","Please avoid using `toString` in this way in production code. I don't see anything in `TypeMirror.toString`'s javadoc that would suggest that the returned string is equal to `@` + annotation type's FQ name, which means that it can change between releases. I think inspecting the type directly via `AnnotationMirror.getAnnotationType` would be more robust",2017-04-25 11:44:56 +751,"@@ -0,0 +1,39 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMember ++import org.jetbrains.kotlin.name.FqName ++ ++abstract class JCMember(tree: T, ++ treePath: TreePath, ++ override val containingClass: JavaClass, ++ javac: Javac) : JCElement(tree, treePath, javac), JavaMember { ++ ++ override val isDeprecatedInJavaDoc = false ++ ++ override val annotations ++ get() = emptyList() ++ ++ override fun findAnnotation(fqName: FqName) = annotations.firstOrNull { it.classId?.asSingleFqName() == fqName }","Again, what do you want to find in the empty list?",2017-04-05 16:20:33 +145,"@@ -0,0 +1,4 @@ ++// ERROR: Too many arguments for public final fun get(index: kotlin.Int): kotlin.Int defined in kotlin.Array","I can't seem to fix the source of this error, so I declared it. +",2014-04-07 07:49:58 +146,"@@ -0,0 +1,4 @@ ++// ERROR: Too many arguments for public final fun get(index: kotlin.Int): kotlin.Int defined in kotlin.Array ++fun foo(a: Array, i: Int) { ++ a[i, { }]","This wouldn't work unless the second argument was a function. Is it still possible to give multiple indices to this construct (i.e, `a[i, 2]`)? +",2014-04-07 07:50:36 +148,"@@ -0,0 +1,4 @@ ++// ERROR: Unresolved reference: !in","I don't understand this error. +",2014-04-07 07:51:14 +108,"@@ -0,0 +1,4 @@ ++// IS_APPLICABLE: false ++fun foo(x: Foo?) { ++ x!!.get(1) ++}","Why not applicable here? `x!![1]` looks pretty okay +",2014-02-07 18:42:01 +48,"@@ -0,0 +1,40 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.jet.lang.psi.JetClass; ++import org.jetbrains.jet.lang.psi.JetFile; ++import org.jetbrains.jet.lang.psi.JetPsiFactory; ++import org.jetbrains.jet.plugin.JetBundle;","A lot of not optimized imports. +When committing, check that you your code is green (no warnings). If you edit some code, assure that you don't introduce new warnings. +",2013-04-26 11:09:38 +481,"@@ -0,0 +1,40 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.incremental.components.LookupTracker ++import org.jetbrains.kotlin.incremental.components.ScopeKind ++import org.jetbrains.kotlin.rmi.CompileService ++import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface ++import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT ++import java.rmi.server.UnicastRemoteObject ++ ++ ++public class RemoteLookupTrackerServer(val base: LookupTracker, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteLookupTracker { ++ ++ init { ++ UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory) ++ } ++ ++ override fun record(lookupContainingFile: String, lookupLine: Int?, lookupColumn: Int?, scopeFqName: String, scopeKind: ScopeKind, name: String) { ++ base.record(lookupContainingFile, lookupLine, lookupColumn, scopeFqName, scopeKind, name) ++ } ++ ++ private val _isDoNothing: Boolean = base == LookupTracker.DO_NOTHING","I think underscore is not needed here +",2015-09-23 14:51:55 +772,"@@ -0,0 +1,40 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.descriptors.ClassDescriptor ++import org.jetbrains.kotlin.descriptors.ConstructorDescriptor ++import org.jetbrains.kotlin.descriptors.PropertyDescriptor ++import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor ++import org.jetbrains.kotlin.load.java.components.AbstractJavaResolverCache ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++import org.jetbrains.kotlin.load.java.structure.JavaField ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.resolve.lazy.ResolveSession ++ ++class JavacBasedJavaResolverCache(resolveSession: ResolveSession) : AbstractJavaResolverCache(resolveSession) {",May be we should name it like `StubJavaResolverCache`. The thing here is obviously not javac based.,2017-04-20 10:18:00 +713,"@@ -0,0 +1,40 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner ++import org.jetbrains.kotlin.load.java.structure.JavaClassifier ++import org.jetbrains.kotlin.name.FqName ++import javax.lang.model.element.Element ++ ++abstract class JavacClassifier(element: T, ++ javac: Javac) : JavacElement(element, javac), JavaClassifier, JavaAnnotationOwner { ++ ++ override val annotations: Collection ++ get() = element.annotationMirrors ++ .map { JavacAnnotation(it, javac) } ++ ++ override fun findAnnotation(fqName: FqName): JavaAnnotation? = element.annotationMirrors ++ .filter { it.toString() == fqName.asString() } ++ .firstOrNull() ++ ?.let { JavacAnnotation(it, javac) } ++ ++ override val isDeprecatedInJavaDoc = false",Why always false?,2017-04-05 14:55:04 +616,"@@ -0,0 +1,40 @@ ++package org.jetbrains.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++ ++class TooLongCharLiteralToStringFix( ++ element: KtConstantExpression ++) : KotlinQuickFixAction(element) { ++ override fun getText(): String = ""Convert too long character literal to string"" ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val text = element.text ++ if (!(text.startsWith(""'"") && text.endsWith(""'"") && text.length >= 2)) { ++ return ++ } ++ ++ val newStringContent = text ++ .slice(1..text.length - 2) ++ .replace(""\\"", ""\\\\"")","For me it's suspicious. We can have a literal like `'Bye\n'` and expect to get `""Bye\n""` as result, so I'd not touch these back slashes. Please add a test for such case. +",2016-09-22 10:49:05 +617,"@@ -0,0 +1,40 @@ ++package org.jetbrains.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++ ++class TooLongCharLiteralToStringFix( ++ element: KtConstantExpression ++) : KotlinQuickFixAction(element) { ++ override fun getText(): String = ""Convert too long character literal to string"" ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val text = element.text ++ if (!(text.startsWith(""'"") && text.endsWith(""'"") && text.length >= 2)) { ++ return ++ } ++ ++ val newStringContent = text ++ .slice(1..text.length - 2) ++ .replace(""\\"", ""\\\\"") ++ .replace(""\"""", ""\\\"""")","Changing double quote to escaped double quote is logical, I think it should be left as is. +",2016-09-22 10:49:57 +615,"@@ -0,0 +1,40 @@ ++package org.jetbrains.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++ ++class TooLongCharLiteralToStringFix( ++ element: KtConstantExpression ++) : KotlinQuickFixAction(element) { ++ override fun getText(): String = ""Convert too long character literal to string"" ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val text = element.text ++ if (!(text.startsWith(""'"") && text.endsWith(""'"") && text.length >= 2)) { ++ return ++ } ++ ++ val newStringContent = text ++ .slice(1..text.length - 2) ++ .replace(""\\"", ""\\\\"") ++ .replace(""\"""", ""\\\"""") ++ val newElement = KtPsiFactory(element).createStringTemplate(newStringContent)","What happens if we have character literal like `'$x'` ? Should we get `""$x""` or `""\$x""`? I'd say the first case (without dollar escaping) is more logical, but I'd add a test for it. +",2016-09-22 10:48:02 +613,"@@ -0,0 +1,40 @@ ++package org.jetbrains.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++ ++class TooLongCharLiteralToStringFix( ++ element: KtConstantExpression ++) : KotlinQuickFixAction(element) { ++ override fun getText(): String = ""Convert too long character literal to string"" ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val text = element.text ++ if (!(text.startsWith(""'"") && text.endsWith(""'"") && text.length >= 2)) { ++ return ++ } ++ ++ val newStringContent = text ++ .slice(1..text.length - 2) ++ .replace(""\\"", ""\\\\"") ++ .replace(""\"""", ""\\\"""") ++ val newElement = KtPsiFactory(element).createStringTemplate(newStringContent) ++ ++ element.replace(newElement) ++ } ++ ++ override fun getFamilyName(): String = ""Strings""","Usually `= text` is in use here. +",2016-09-22 10:44:22 +749,"@@ -0,0 +1,41 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaPackage ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++ ++class JCPackage(val name: String, val javac: Javac) : JavaPackage { ++ ++ override val fqName: FqName ++ get() = FqName(name)",Consider making it an initializer and remove getter,2017-04-05 16:15:12 +834,"@@ -0,0 +1,41 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaPackage ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++ ++class TreeBasedPackage(val name: String, val javac: JavacWrapper) : JavaPackage {","Similarly to `SymbolBasedPackage`, I think it can inherit from `SymbolBasedElement` and avoid overriding `equals`/`hashCode`/`toString`",2017-04-25 16:41:11 +833,"@@ -0,0 +1,41 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaPackage ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++ ++class TreeBasedPackage(val name: String, val javac: JavacWrapper) : JavaPackage { ++ ++ override val fqName ++ get() = FqName(name) ++ ++ override val subPackages ++ get() = javac.findSubPackages(fqName) ++ ++ override fun getClasses(nameFilter: (Name) -> Boolean) = javac.findClassesFromPackage(fqName)","Shouldn't `TreeBasedPackage` contain only `TreeBasedClass`es, and `SymbolBasedPackage` -- only `SymbolBasedClass`es?",2017-04-25 16:40:20 +704,"@@ -0,0 +1,42 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache ++import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass ++import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.wrappers.trees.computeClassId ++ ++ ++abstract class JavacVirtualFileFinder : VirtualFileFinder() { ++ ++ override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? { ++ var file = javaClass.computeClassId()?.let(this::findVirtualFileWithHeader) ?: return null ++ ++ if (javaClass.outerClass != null) { ++ // For nested classes we get a file of the containing class, to get the actual class file for A.B.C, ++ // we take the file for A, take its parent directory, then in this directory we look for A$B$C.class ++ file = file.parent!!.findChild(classFileName(javaClass) + "".class"").sure { ""Virtual file not found for $javaClass"" }","Again, it's better not to repeat the same code. Extract some protected function from `VirtualFileFinder`",2017-04-05 13:02:31 +703,"@@ -0,0 +1,42 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache ++import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass ++import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.wrappers.trees.computeClassId ++ ++ ++abstract class JavacVirtualFileFinder : VirtualFileFinder() { ++ ++ override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? { ++ var file = javaClass.computeClassId()?.let(this::findVirtualFileWithHeader) ?: return null ++ ++ if (javaClass.outerClass != null) { ++ // For nested classes we get a file of the containing class, to get the actual class file for A.B.C, ++ // we take the file for A, take its parent directory, then in this directory we look for A$B$C.class ++ file = file.parent!!.findChild(classFileName(javaClass) + "".class"").sure { ""Virtual file not found for $javaClass"" } ++ } ++ ++ return KotlinBinaryClassCache.getKotlinBinaryClass(file) ++ } ++ ++ inline fun T?.sure(message: () -> String): T = this ?: throw AssertionError(message())",This function already exists (anyway you will not need it after processing the previous comment),2017-04-05 13:00:31 +765,"@@ -0,0 +1,42 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.codeInsight.intention.LowPriorityAction ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.KtDeclaration ++import org.jetbrains.kotlin.psi.KtFunction ++import org.jetbrains.kotlin.psi.KtProperty ++import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType ++ ++class AddOpenModifierIntention : SelfTargetingIntention(KtDeclaration::class.java, ""Make open""), LowPriorityAction { ++ override fun isApplicableTo(element: KtDeclaration, caretOffset: Int): Boolean { ++ if (element.hasModifier(KtTokens.OPEN_KEYWORD) || element.hasModifier(KtTokens.PRIVATE_KEYWORD)) return false ++ when (element) { ++ is KtProperty -> if (element.isLocal) return false ++ is KtFunction -> if (element.isLocal) return false ++ } ++ val ktClass = element.getNonStrictParentOfType() ?: return false ++ return ktClass.hasModifier(KtTokens.OPEN_KEYWORD)","Things are not so easy here. First of all, there is `KtDeclaration.implicitModality()`, please use it. For example, interface functions with body are implicitly open and do not require explicit open modifier. Also, you need `containingClassOrObject` and not `getNonStrictParentOfType`, you are risking to miss e.g. companion object in the middle this way. Remember also that object / interface members should never have `open` added, as well as top-level guys. And at last, class can have `open` members if it's `open`, `abstract` or `sealed` itself, I'd not limit it to just open classes as described in an issue. ",2017-04-18 06:59:02 +812,"@@ -0,0 +1,42 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaPackage ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.PackageElement ++ ++class SymbolBasedPackage(val element: PackageElement, val javac: JavacWrapper) : JavaPackage {",Why doesn't it inherit from `SymbolBasedElement` to get `equals`/`hashCode`/`toString` for free?,2017-04-25 12:33:45 +555,"@@ -0,0 +1,43 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtLambdaExpression ++import org.jetbrains.kotlin.psi.KtPsiFactory ++ ++class AddRunToLambdaFix(element: KtLambdaExpression) : KotlinQuickFixAction(element) { ++ override fun getText() = ""Add 'run' before the lambda expression"" ++ override fun getFamilyName() = ""Add 'run' before the lambda expression""","`= getText()` +",2016-05-06 15:32:20 +804,"@@ -0,0 +1,43 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaField ++import javax.lang.model.element.ElementKind ++import javax.lang.model.element.VariableElement ++ ++class SymbolBasedField(element: T, ++ javac: JavacWrapper) : SymbolBasedMember(element, javac), JavaField { ++ ++ override val isEnumEntry ++ get() = element.kind == ElementKind.ENUM_CONSTANT ++ ++ override val type ++ get() = SymbolBasedType.create(element.asType(), javac) ++ ++ override val initializerValue: Any? ++ get() = element.constantValue ++ ++ override val hasConstantNotNullInitializer ++ get() = element.constantValue?.let { ++ val typeMirror = type.typeMirror ++ ++ (typeMirror.kind.isPrimitive || typeMirror.toString() == ""java.lang.String"")","Please inspect the underlying element instead of `toString`. +",2017-04-25 12:16:15 +788,"@@ -0,0 +1,43 @@ ++package test ++ ++public/*package*/ open class ExtendsAbstractListT { ++ public/*package*/ constructor ExtendsAbstractListT() ++} ++ ++public abstract class Mine : java.util.AbstractList { ++ public constructor Mine() ++ protected/*protected and package*/ final /*fake_override*/ var modCount: kotlin.Int ++ public abstract /*fake_override*/ val size: kotlin.Int ++ public open /*fake_override*/ fun add(/*0*/ T!): kotlin.Boolean ++ public open /*fake_override*/ fun add(/*0*/ kotlin.Int, /*1*/ T!): kotlin.Unit ++ public open /*fake_override*/ fun addAll(/*0*/ kotlin.Int, /*1*/ kotlin.collections.Collection): kotlin.Boolean ++ public open /*fake_override*/ fun addAll(/*0*/ kotlin.collections.Collection): kotlin.Boolean ++ public open /*fake_override*/ fun clear(): kotlin.Unit ++ public open /*fake_override*/ fun contains(/*0*/ T!): kotlin.Boolean ++ public open /*fake_override*/ fun containsAll(/*0*/ kotlin.collections.Collection): kotlin.Boolean ++ public open /*fake_override*/ fun forEach(/*0*/ java.util.function.Consumer!): kotlin.Unit","Do I understand correctly that `xxx2.txt` differs from `xxx.txt` only in members that come from Java 8 and this is caused by the fact that the original test was run against JDK 6, but the test with javac is run against JDK 8? + +I suggest just using JDK 8 then in both tests, to avoid complicating things too much.",2017-04-25 10:04:28 +717,"@@ -0,0 +1,44 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaPackage ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.PackageElement ++ ++class JavacPackage(val element: PackageElement, val javac: Javac) : JavaPackage { ++ ++ override val fqName ++ get() = element.qualifiedName.let { FqName(it.toString()) }",I'd consider removing `let` from this and next getter. I suppose code without it will be easier to read,2017-04-05 15:07:21 +718,"@@ -0,0 +1,44 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaPackage ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.PackageElement ++ ++class JavacPackage(val element: PackageElement, val javac: Javac) : JavaPackage { ++ ++ override val fqName ++ get() = element.qualifiedName.let { FqName(it.toString()) } ++ ++ override val subPackages ++ get() = javac.findSubPackages(element.qualifiedName.toString().let(::FqName)) ++ ++ override fun getClasses(nameFilter: (Name) -> Boolean) = javac.findClassesFromPackage(fqName) ++ .filter { Name.isValidIdentifier(it.name.toString()) ++ && nameFilter(Name.identifier(it.name.toString())) ++ } ++ ++ override fun hashCode() = element.hashCode() ++ ++ override fun equals(other: Any?) = (other as? JavacPackage)?.element == element",Why do you need to override `equals` from `JavacElement` here?,2017-04-05 15:07:52 +426,"@@ -0,0 +1,45 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr","It seems this file should be placed in the appropriate subdirectory in order to get rid of warning about file location? +",2015-08-20 14:48:32 +417,"@@ -0,0 +1,45 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.rmi.RemoteOutputStream ++import java.io.OutputStream ++import java.rmi.server.UnicastRemoteObject ++ ++ ++class RemoteOutputStreamServer(val out: OutputStream) : RemoteOutputStream {","`: RemoteOutputStream by out` +",2015-08-20 13:33:53 +425,"@@ -0,0 +1,45 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.kotlinr ++ ++import org.jetbrains.kotlin.rmi.RemoteOutputStream ++import java.io.OutputStream ++import java.rmi.server.UnicastRemoteObject ++ ++ ++class RemoteOutputStreamServer(val out: OutputStream) : RemoteOutputStream { ++ ++ init { ++ UnicastRemoteObject.exportObject(this, 0) ++ } ++ ++ public fun disconnect() { ++ UnicastRemoteObject.unexportObject(this, true) ++ } ++ ++ override fun close() { ++ out.close() ++ } ++ ++ override fun write(data: ByteArray, start: Int, length: Int) {","`start` -> `offset` (as in the supertype) in order to get rid of corresponding warning. +",2015-08-20 14:45:47 +109,"@@ -0,0 +1,46 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import org.jetbrains.jet.lang.psi.JetQualifiedExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetValueArgument ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++ ++ ++public class BracketToGetIntention : JetSelfTargetingIntention(""bracket.to.get"", javaClass()) { ++ override fun isApplicableTo(element: JetArrayAccessExpression): Boolean { ++ return element is JetArrayAccessExpression ++ } ++ ++ override fun applyTo(element: JetArrayAccessExpression, editor: Editor) { ++ val array = element.getArrayExpression()!! ++ val indices = element.getIndexExpressions() ++ ++ val arrayText = array.getText() ++ val indicesText = indices.map { it.getText() }.makeString("", "")","This line feels like a hack. It also doesn't preserve comments. Is there any way to get the contents of the indices without losing comments? +",2014-02-08 22:34:13 +583,"@@ -0,0 +1,46 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.editor.wordSelection ++ ++import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElement ++import org.jetbrains.kotlin.psi.KtTypeReference ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class KotlinFunctionReturnTypeSelectioner : ExtendWordSelectionHandlerBase() { ++ ++ override fun canSelect(e: PsiElement?): Boolean { ++ return e is KtTypeReference ++ } ++ ++ override fun select(e: PsiElement?, editorText: CharSequence?, cursorOffset: Int, editor: Editor): List? { ++ e ?: return null ++ editorText ?: return null ++ val position = getColonPosition(e, editorText) ++ if (position < 0) return null ++ return listOf(TextRange(position, e.endOffset)) ++ } ++ ++ private fun getColonPosition(e: PsiElement, editorText: CharSequence): Int { ++ val colonIndex = editorText.filterIndexed { i, c -> i < e.startOffset }.indexOfLast { it == ':' }","Please do not use the text or regular expressions to perform the action. All the necessary information is available in the PSI; please do use it. +",2016-07-18 20:59:44 +655,"@@ -0,0 +1,46 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtForExpression ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.createExpressionByPattern ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++ ++class ConvertRangeCheckToTwoComparisonsIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, ""Convert to comparisons"") { ++ override fun applyTo(element: KtBinaryExpression, editor: Editor?) { ++ if (element.operationToken != KtTokens.IN_KEYWORD) return ++ val rangeExpression = element.right as? KtBinaryExpression ?: return ++ val min = rangeExpression.left?.text ?: return ++ val arg = element.left?.text ?: return ++ val max: Any = rangeExpression.right?.text ?: return",Why do you need `Any` here?,2016-12-13 10:24:27 +654,"@@ -0,0 +1,46 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtForExpression ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.createExpressionByPattern ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++ ++class ConvertRangeCheckToTwoComparisonsIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, ""Convert to comparisons"") { ++ override fun applyTo(element: KtBinaryExpression, editor: Editor?) { ++ if (element.operationToken != KtTokens.IN_KEYWORD) return ++ val rangeExpression = element.right as? KtBinaryExpression ?: return ++ val min = rangeExpression.left?.text ?: return ++ val arg = element.left?.text ?: return ++ val max: Any = rangeExpression.right?.text ?: return ++ val comparisonsExpression = KtPsiFactory(element).createExpressionByPattern(""$0 <= $1 && $1 <= $2"", min, arg, max) ++ element.replace(comparisonsExpression) ++ } ++ ++ override fun isApplicableTo(element: KtBinaryExpression): Boolean { ++ if (element.operationToken != KtTokens.IN_KEYWORD) return false ++ // ignore for-loop. for(x in 1..2) should not be convert to for(1<=x && x<=2) ++ if (element.getStrictParentOfType() != null) return false","I'd say this condition is too strict. E.g. your intention will not work for code like + +``` +for (element in list) { + if (element in 1..4) { ... } +} +```",2016-12-13 10:23:40 +542,"@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.codegen.intrinsics ++ ++import org.jetbrains.kotlin.codegen.ExpressionCodegen ++import org.jetbrains.kotlin.codegen.StackValue ++import org.jetbrains.kotlin.descriptors.ConstructorDescriptor ++import org.jetbrains.kotlin.psi.KtCallableReferenceExpression ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall ++import org.jetbrains.kotlin.resolve.jvm.AsmTypes ++import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver ++import org.jetbrains.org.objectweb.asm.Type ++ ++class KCallableNameProperty : IntrinsicPropertyGetter() { ++ override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? { ++ val expressionReceiver = resolvedCall!!.dispatchReceiver as? ExpressionReceiver ?: return null ++ val expression = expressionReceiver.expression as? KtCallableReferenceExpression ?: return null ++ val callableReference = expression.callableReference ++ val descriptor = callableReference.getResolvedCall(codegen.bindingContext)?.resultingDescriptor ?: return null ++ ++ val name = if (descriptor is ConstructorDescriptor) {","`descriptor.name.asString()` +",2016-04-22 19:46:23 +782,"@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.load.java ++ ++import org.jetbrains.kotlin.load.java.structure.impl.JavaPackageImpl ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer ++import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade ++import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer ++ ++import javax.annotation.PostConstruct ++ ++class JavaClassFinderImpl : AbstractJavaClassFinder() { ++ ++ private lateinit var javaFacade: KotlinJavaPsiFacade ++ ++ @PostConstruct ++ fun initialize(trace: BindingTrace, codeAnalyzer: KotlinCodeAnalyzer) { ++ javaSearchScope = FilterOutKotlinSourceFilesScope(baseScope)",Please extract the first and the third line of this method into `AbstractJavaClassFinder.initialize` and call it here and in `JavacBasedClassFinder.initialize`,2017-04-25 08:08:33 +783,"@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.load.java ++ ++import org.jetbrains.kotlin.load.java.structure.impl.JavaPackageImpl ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer ++import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade ++import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer ++ ++import javax.annotation.PostConstruct ++ ++class JavaClassFinderImpl : AbstractJavaClassFinder() { ++ ++ private lateinit var javaFacade: KotlinJavaPsiFacade ++ ++ @PostConstruct ++ fun initialize(trace: BindingTrace, codeAnalyzer: KotlinCodeAnalyzer) { ++ javaSearchScope = FilterOutKotlinSourceFilesScope(baseScope) ++ javaFacade = KotlinJavaPsiFacade.getInstance(proj) ++ CodeAnalyzerInitializer.getInstance(proj).initialize(trace, codeAnalyzer.moduleDescriptor, codeAnalyzer) ++ } ++ ++ ++ override fun findClass(classId: ClassId) = javaFacade.findClass(classId, javaSearchScope)",Please do not omit return types at least where inspections are reported (there's an inspection about platform type here).,2017-04-25 08:10:49 +903,"@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.codeInsight.intention.LowPriorityAction ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.inspections.UnusedSymbolInspection ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.idea.util.findAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.KtNamedFunction ++import org.jetbrains.kotlin.psi.KtObjectDeclaration ++ ++class AddJvmStaticIntention : SelfTargetingIntention( ++ KtNamedFunction::class.java, ++ ""Add '@JvmStatic' annotation"" ++), LowPriorityAction { ++ ++ private val annotationFqName = FqName(""kotlin.jvm.JvmStatic"") ++ ++ override fun isApplicableTo(element: KtNamedFunction, caretOffset: Int): Boolean { ++ if (element.findAnnotation(annotationFqName) != null) return false ++ if (!UnusedSymbolInspection.isEntryPoint(element)) return false",See `KotlinRunLineMarkerContributor` for the correct way to check that a function is `main`.,2017-07-17 11:21:50 +904,"@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.codeInsight.intention.LowPriorityAction ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.inspections.UnusedSymbolInspection ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.idea.util.findAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.KtNamedFunction ++import org.jetbrains.kotlin.psi.KtObjectDeclaration ++ ++class AddJvmStaticIntention : SelfTargetingIntention( ++ KtNamedFunction::class.java, ++ ""Add '@JvmStatic' annotation"" ++), LowPriorityAction { ++ ++ private val annotationFqName = FqName(""kotlin.jvm.JvmStatic"") ++ ++ override fun isApplicableTo(element: KtNamedFunction, caretOffset: Int): Boolean { ++ if (element.findAnnotation(annotationFqName) != null) return false ++ if (!UnusedSymbolInspection.isEntryPoint(element)) return false ++ element.parent.parent.run {",Please use `KtDeclaration.containingClassOrObject`.,2017-07-17 11:23:10 +469,"@@ -0,0 +1,48 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.io.IOException ++import java.io.Serializable ++import java.net.InetAddress ++import java.net.ServerSocket ++import java.net.Socket ++import java.rmi.server.RMIClientSocketFactory ++import java.rmi.server.RMIServerSocketFactory ++ ++ ++// TODO switch to InetAddress.getLoopbackAddress on java 7+ ++val loopbackAddrName by lazy { if (java.net.InetAddress.getLocalHost() is java.net.Inet6Address) ""::1"" else ""127.0.0.1"" }","`java.net.InetAddress.getLocalHost()` may crash with IOException (actually, UnknownHostException) on some machines due to strange network configuration. Notice that it is not a wrong machine configuration but Java's limitation. In some cases it couldn't be fixed on some corporate machines. I faced it few times in different companies. It is possible at least on Linux and Solaris machines +",2015-09-08 18:13:12 +750,"@@ -0,0 +1,48 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.load.java.structure.JavaValueParameter ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++ ++class JCValueParameter(tree: T, ++ treePath: TreePath, ++ javac: Javac) : JCElement(tree, treePath, javac), JavaValueParameter { ++ ++ override val annotations: Collection ++ get() = emptyList()",Value parameter in Java can have annotations,2017-04-05 16:17:43 +584,"@@ -0,0 +1,49 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.editor.wordSelection ++ ++import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElement ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.KtSuperTypeList ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class KotlinSuperTypeSelectioner : ExtendWordSelectionHandlerBase() { ++ override fun canSelect(e: PsiElement?): Boolean { ++ return e is KtSuperTypeList ++ } ++ ++ override fun select(e: PsiElement?, editorText: CharSequence?, cursorOffset: Int, editor: Editor): List? { ++ e ?: return null","Those parameters are actually non-null. You don't need the null checks here and in the other selectioner. +",2016-07-22 18:17:04 +585,"@@ -0,0 +1,49 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.editor.wordSelection ++ ++import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElement ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.KtSuperTypeList ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class KotlinSuperTypeSelectioner : ExtendWordSelectionHandlerBase() { ++ override fun canSelect(e: PsiElement?): Boolean { ++ return e is KtSuperTypeList ++ } ++ ++ override fun select(e: PsiElement?, editorText: CharSequence?, cursorOffset: Int, editor: Editor): List? { ++ e ?: return null ++ editorText ?: return null ++ val colonPosition = getColonPosition(e) ++ if (colonPosition < 0) return null ++ return listOf(TextRange(colonPosition, e.endOffset)) ++ } ++ ++ private fun getColonPosition(e: PsiElement): Int { ++ var parent = e.parent","You can use the `PsiElement.getParentOfType()` extension function to do this with less code. +",2016-07-22 18:17:50 +818,"@@ -0,0 +1,49 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedTypeParameter(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaTypeParameter { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.name.toString())",`Name.identifier`,2017-04-25 13:09:56 +819,"@@ -0,0 +1,49 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.SpecialNames ++ ++class TreeBasedTypeParameter(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedElement(tree, treePath, javac), JavaTypeParameter { ++ ++ override val name ++ get() = SpecialNames.safeIdentifier(tree.name.toString()) ++ ++ override val annotations by lazy { tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) } } ++ ++ override fun findAnnotation(fqName: FqName) = annotations.firstOrNull { it.classId?.asSingleFqName() == fqName } ++ ++ override val isDeprecatedInJavaDoc ++ get() = findAnnotation(FqName(""java.lang.Deprecated"")) != null",You should return `false` here and in other implementations of `isDeprecatedInJavaDoc`. The call site looks for the annotation itself if needed,2017-04-25 13:23:18 +147,"@@ -0,0 +1,5 @@ ++// ERROR: Unresolved reference: array","I don't understand this error. +",2014-04-07 07:51:03 +623,"@@ -0,0 +1,5 @@ ++ ++ ++ This intention detects 'Math.max' calls that can be safely replaced with 'coerceAtLeast'","This intention replaces 'Math.max' calls with safe 'coerceAtLeast' ... or something like. Inspection detects, but inspection does some change. +",2016-09-26 10:58:15 +560,"@@ -0,0 +1,5 @@ ++ ++ ++Reports unnecessary java usage.","This is not clear. A better description would be ""Use of Java API that has a Kotlin equivalent"" or something like that. +",2016-05-18 13:22:55 +631,"@@ -0,0 +1,5 @@ ++ ++ ++This inspection remove an empty class body","reports and offers to remove +",2016-10-10 11:02:44 +659,"@@ -0,0 +1,5 @@ ++ ++ ++This inspection reports unused equals expression.",expression**s**,2016-12-23 09:31:28 +621,"@@ -0,0 +1,5 @@ ++ ++ ++This intention detects 'Math.max' calls that can be safely replaced with 'coerceAtLeast'","inspection +",2016-09-26 10:56:49 +622,"@@ -0,0 +1,5 @@ ++ ++ ++This intention detects 'Math.min' calls that can be safely replaced with 'coerceAtMost'","inspection +",2016-09-26 10:56:58 +632,"@@ -0,0 +1,5 @@ ++ ++ ++This intention detects an empty class body.","removes +",2016-10-10 11:04:11 +186,"@@ -0,0 +1,5 @@ ++ ++ ++This intention makes types explicit in a lambda expression.","A little elaboration won't hurt: `types of parameters, receiver and return type` +",2014-04-16 23:44:55 +187,"@@ -0,0 +1,5 @@ ++ ++ ++This intention makes types implicit in a lambda expression","Ditto +",2014-04-16 23:45:02 +101,"@@ -0,0 +1,5 @@ ++ ++ ++This intention take a qualified call to any function ""get"" which has some arguments and converts it to square brackets.","""takes"" +",2014-02-06 14:39:06 +511,"@@ -0,0 +1,5 @@ ++fun box(): String { ++ val sub = Box(-1) ++ println(sub.value == 1L)","replace 'println' with if check +",2016-02-09 08:34:22 +224,"@@ -0,0 +1,5 @@ ++if (foo()) { ++ bar() ++} else { ++ baz() ++}","The branches aren't swapped in the after-template +",2014-05-03 10:49:59 +955,"@@ -0,0 +1,5 @@ ++package org.junit ++ ++@Deprecated(""Use 'Ignore' from kotlin.test package"", replaceWith = ReplaceWith(""Ignore"", imports = ""kotlin.test.Ignore"")) ++@Suppress(""HEADER_WITHOUT_IMPLEMENTATION"") ++header annotation class Ignore",I'm working on not needing this...,2017-08-11 20:44:29 +786,"@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer ++import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer ++import javax.annotation.PostConstruct ++ ++class JavacBasedClassFinder : AbstractJavaClassFinder() { ++ ++ private lateinit var javac: JavacWrapper ++ ++ @PostConstruct ++ fun initialize(trace: BindingTrace, codeAnalyzer: KotlinCodeAnalyzer) { ++ javaSearchScope = FilterOutKotlinSourceFilesScope(baseScope) ++ javac = JavacWrapper.getInstance(proj) ++ CodeAnalyzerInitializer.getInstance(proj).initialize(trace, codeAnalyzer.moduleDescriptor, codeAnalyzer) ++ } ++ ++ override fun findClass(classId: ClassId) = javac.findClass(classId.asSingleFqName(), javaSearchScope)","Note that `ClassId.asSingleFqName` is an operation that loses some information, namely where package name in the `FqName` ends and where the class name starts. For example, `FqName` ""a.b.c"" might mean class c nested in class b in package a, or it might mean class c in package a.b. + +Please consider either using `ClassId` when possible, or at least destructuring it into package FQ name and relative class name and using them, to avoid problems related to resolution of nested classes.",2017-04-25 08:25:38 +785,"@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer ++import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer ++import javax.annotation.PostConstruct ++ ++class JavacBasedClassFinder : AbstractJavaClassFinder() { ++ ++ private lateinit var javac: JavacWrapper ++ ++ @PostConstruct ++ fun initialize(trace: BindingTrace, codeAnalyzer: KotlinCodeAnalyzer) { ++ javaSearchScope = FilterOutKotlinSourceFilesScope(baseScope) ++ javac = JavacWrapper.getInstance(proj) ++ CodeAnalyzerInitializer.getInstance(proj).initialize(trace, codeAnalyzer.moduleDescriptor, codeAnalyzer) ++ } ++ ++ override fun findClass(classId: ClassId) = javac.findClass(classId.asSingleFqName(), javaSearchScope) ++ ++ override fun findPackage(fqName: FqName) = javac.findPackage(fqName, javaSearchScope) ++ ++ override fun knownClassNamesInPackage(packageFqName: FqName): Set = javac.findClassesFromPackage(packageFqName) ++ .mapNotNullTo(hashSetOf()) { ++ it.fqName?.let { ++ if (it.isRoot) it.asString() else it.shortName().asString()","Multiple `it`s in nested lambdas are dangerous and confusing, please rename at least one of them",2017-04-25 08:18:38 +887,"@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.psi.* ++ ++class RemoveRedundantBackticksInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitCallExpression(expression: KtCallExpression) {","Why is this limited to call expressions? Backticks can be used around any occurrence of identifier in Kotlin code, and the inspection should detect those in any context.",2017-07-10 09:03:51 +888,"@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.psi.* ++ ++class RemoveRedundantBackticksInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitCallExpression(expression: KtCallExpression) { ++ super.visitCallExpression(expression) ++ val calleeExpression = expression.calleeExpression ?: return ++ if (calleeExpression.text.contains(""^`.+`$"".toRegex())) {","This detects any backticks, not just redundant backticks. Backticks are redundant only if they enclose a valid identifier (not a keyword and not containing any invalid characters).",2017-07-10 09:04:46 +755,"@@ -0,0 +1,51 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer ++import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer ++import javax.annotation.PostConstruct ++ ++class JavacBasedClassFinder : AbstractJavaClassFinder() { ++ ++ private lateinit var javac: JavacWrapper ++ ++ @PostConstruct ++ fun initialize(trace: BindingTrace, codeAnalyzer: KotlinCodeAnalyzer) { ++ javaSearchScope = FilterOutKotlinSourceFilesScope(baseScope) ++ javac = JavacWrapper.getInstance(proj) ++ CodeAnalyzerInitializer.getInstance(proj).initialize(trace, codeAnalyzer.moduleDescriptor, codeAnalyzer) ++ } ++ ++ override fun findClass(classId: ClassId) = javac.findClass(classId.asSingleFqName(), javaSearchScope) ++ ++ override fun findPackage(fqName: FqName) = javac.findPackage(fqName, javaSearchScope) ++ ++ override fun knownClassNamesInPackage(packageFqName: FqName) = javac.findClassesFromPackage(packageFqName) ++ .mapNotNull {","Here you can use `mapNotNullTo` without `toSet` at the end, it may be a bit faster",2017-04-11 10:03:58 +933,"@@ -0,0 +1,51 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.quickfix ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.util.PsiTreeUtil ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType ++ ++class RemoveUselessIsCheckFixForWhen(element: KtWhenConditionIsPattern) : KotlinQuickFixAction(element) { ++ override fun getFamilyName() = ""Remove useless is check"" ++ ++ override fun getText(): String = familyName ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val condition = element ?: return ++ val whenEntry = condition.parent as KtWhenEntry ++ val whenExpression = whenEntry.parent as KtWhenExpression ++ ++ if (condition.isNegated) { ++ condition.parent.delete() ++ } else { ++ whenExpression.entries.forEach { it.delete() }","You should not delete all entries here, but only subsequent ones. E.g. + +``` +val something: Base = ... +when (something) { + is Derived -> forDerived() + is Base /* always true */ -> forBase() + is Any /* unreachable */ -> forAny() + is SomethingWrong /* also unreachable */ forWrong() + else -> forElse() +} +``` + +Here `is Base` branch must be left intact.",2017-07-26 14:59:07 +404,"@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2010-2015 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 kotlin.collections","Why not `package kotlin`? +",2015-07-29 17:28:08 +639,"@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.refactoring.rename.RenameProcessor ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier ++ ++class ValToObjectIntention : SelfTargetingIntention(KtProperty::class.java, ""Convert to object declaration"") { ++ ++ override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean { ++ if (element.isVar) return false ++ if (!element.isTopLevel) return false ++ if (element.initializer !is KtObjectLiteralExpression) return false ++ if (element.getter != null) return false ++ ++ return true ++ } ++ ++ override fun applyTo(element: KtProperty, editor: Editor?) { ++ val modifier = element.visibilityModifier()","You're losing all annotations on the original property. (I think that it would be best not to offer the intention if the property has any, because the semantics of annotations on a `val` and an `object` is significantly different.) +",2016-10-14 10:53:34 +640,"@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.refactoring.rename.RenameProcessor ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier ++ ++class ValToObjectIntention : SelfTargetingIntention(KtProperty::class.java, ""Convert to object declaration"") { ++ ++ override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean { ++ if (element.isVar) return false ++ if (!element.isTopLevel) return false ++ if (element.initializer !is KtObjectLiteralExpression) return false ++ if (element.getter != null) return false ++ ++ return true ++ } ++ ++ override fun applyTo(element: KtProperty, editor: Editor?) { ++ val modifier = element.visibilityModifier() ++ val name = element.name ?: return ++ val o = element.initializer as? KtObjectLiteralExpression ?: return ++ val od = o.objectDeclaration ++ val superTypeList = od.getSuperTypeList() ?: return","I think you should check the supertype list in `isApplicableTo` as well, so that you don't end up with an intention which is enabled and does nothing. +",2016-10-14 10:54:38 +638,"@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.refactoring.rename.RenameProcessor ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier ++ ++class ValToObjectIntention : SelfTargetingIntention(KtProperty::class.java, ""Convert to object declaration"") { ++ ++ override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean { ++ if (element.isVar) return false ++ if (!element.isTopLevel) return false ++ if (element.initializer !is KtObjectLiteralExpression) return false ++ if (element.getter != null) return false ++ ++ return true ++ } ++ ++ override fun applyTo(element: KtProperty, editor: Editor?) { ++ val modifier = element.visibilityModifier() ++ val name = element.name ?: return ++ val o = element.initializer as? KtObjectLiteralExpression ?: return ++ val od = o.objectDeclaration ++ val superTypeList = od.getSuperTypeList() ?: return ++ val body = od.getBody() ?: return ++ ++ val prefix = modifier?.text?.plus("" "") ?: """" ++ val replacementText = ""${prefix}object $name: ${superTypeList.text} ${body.text}"" ++ val replaced = element.replaced(KtPsiFactory(element).createDeclarationByPattern(replacementText)) ++ ++ RenameProcessor(element.project, replaced, name.capitalize(), false, false).doRun()","I think that automatically changing the name without user input is not a very good idea. It's better to trigger a rename refactoring where the user inputs the name, initialized with the capitalized version of the old name. +",2016-10-14 10:51:49 +625,"@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection ++import org.jetbrains.kotlin.psi.KtCallExpression ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe ++ ++class ReplaceMathMaxWithCoerceAtLeastInspection : IntentionBasedInspection(ReplaceMathMaxWithCoerceAtLeastIntention::class) ++ ++class ReplaceMathMaxWithCoerceAtLeastIntention() : SelfTargetingOffsetIndependentIntention(","I think abstract class should be extracted from this intention and the next one. Too many similar code inside +",2016-09-26 11:04:32 +624,"@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection ++import org.jetbrains.kotlin.psi.KtCallExpression ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe ++ ++class ReplaceMathMaxWithCoerceAtLeastInspection : IntentionBasedInspection(ReplaceMathMaxWithCoerceAtLeastIntention::class) ++ ++class ReplaceMathMaxWithCoerceAtLeastIntention() : SelfTargetingOffsetIndependentIntention( ++ KtCallExpression::class.java, ""Replace Math.max with coerceAtLeast"") { ++ ++ override fun applyTo(element: KtCallExpression, editor: Editor?) { ++ val target = element.getStrictParentOfType() ?: element ++ val valueArguments = element.valueArguments ++ val newExpression = KtPsiFactory(element).createExpression(""${valueArguments[0].text}.coerceAtLeast(${valueArguments[1].text})"") ++ target.replaced(newExpression) ++ } ++ ++ override fun isApplicableTo(element: KtCallExpression) = isMaxMethod(element) ++ ++ private fun isMaxMethod(element: KtCallExpression) = ++ element.calleeExpression?.text == ""max"" && element.valueArguments.size == 2 && element.isMethodCall(""java.lang.Math.max"") ++ ++ private fun KtCallExpression.isMethodCall(fqMethodName: String): Boolean {","You have the same method in `ReplaceMathMinWithCoerceAtMostIntention`. It would make more sense to pull it out in a Utils class. +",2016-09-26 11:01:50 +802,"@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument ++import org.jetbrains.kotlin.load.java.structure.JavaArrayAnnotationArgument ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.AnnotationMirror ++import javax.lang.model.element.AnnotationValue ++import javax.lang.model.element.VariableElement ++import javax.lang.model.type.TypeMirror ++ ++open class SymbolBasedAnnotationArgument(private val fqName: FqName,","Annotation argument has no FQ name, a `Name` should be enough",2017-04-25 12:06:23 +721,"@@ -0,0 +1,53 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.FqName ++import javax.lang.model.type.TypeKind ++import javax.lang.model.type.TypeMirror ++ ++open class JavacType(val typeMirror: T, ++ val javac: Javac) : JavaType, JavaAnnotationOwner { ++ ++ companion object { ++ fun create(t: TM, javac: Javac) = when { ++ t.kind.isPrimitive || t.toString() == ""void"" -> JavacPrimitiveType(t, javac)",Why the second part is needed? Looks like `TypeMirror` for `void` also should be primitive? You can also consider extracting this condition as `if` and continue with `when (t.kind)`.,2017-04-05 15:13:45 +722,"@@ -0,0 +1,53 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.FqName ++import javax.lang.model.type.TypeKind ++import javax.lang.model.type.TypeMirror ++ ++open class JavacType(val typeMirror: T, ++ val javac: Javac) : JavaType, JavaAnnotationOwner { ++ ++ companion object { ++ fun create(t: TM, javac: Javac) = when { ++ t.kind.isPrimitive || t.toString() == ""void"" -> JavacPrimitiveType(t, javac) ++ t.kind == TypeKind.DECLARED || t.kind == TypeKind.TYPEVAR -> JavacClassifierType(t, javac) ++ t.kind == TypeKind.WILDCARD -> JavacWildcardType(t, javac) ++ t.kind == TypeKind.ARRAY -> JavacArrayType(t, javac) ++ else -> throw UnsupportedOperationException(""Unsupported type: $t"") ++ } ++ } ++ ++ override val annotations: Collection = emptyList() ++ ++ override val isDeprecatedInJavaDoc ++ get() = false ++ ++ override fun findAnnotation(fqName: FqName) = null",`annotations` and `findAnnotation` are implemented in a different way in NB plugin,2017-04-05 15:15:17 +744,"@@ -0,0 +1,53 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaConstructor ++import org.jetbrains.kotlin.name.Name ++ ++class JCConstructor(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaConstructor { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract",Constructor never can be abstract,2017-04-05 16:06:44 +742,"@@ -0,0 +1,53 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaConstructor ++import org.jetbrains.kotlin.name.Name ++ ++class JCConstructor(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaConstructor { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic",Constructor never can be static,2017-04-05 16:05:51 +743,"@@ -0,0 +1,53 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaConstructor ++import org.jetbrains.kotlin.name.Name ++ ++class JCConstructor(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaConstructor { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal",Also it never can be overridable. Not sure should it be considered as `final` or not.,2017-04-05 16:06:27 +739,"@@ -0,0 +1,54 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaField ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.Name ++ ++class JCField(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaField { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = if (containingClass.isInterface) true else tree.modifiers.isStatic",`containingClass.isInterface || tree.modifiers.isStatic`,2017-04-05 16:00:34 +790,"@@ -0,0 +1,54 @@ ++package test ++ ++public final annotation class AByte : kotlin.Annotation { ++ public constructor AByte(/*0*/ kotlin.Byte) ++ public final val value: kotlin.Byte ++} ++ ++public final annotation class AChar : kotlin.Annotation { ++ public constructor AChar(/*0*/ kotlin.Char) ++ public final val value: kotlin.Char ++} ++ ++public final annotation class ADouble : kotlin.Annotation { ++ public constructor ADouble(/*0*/ kotlin.Double) ++ public final val value: kotlin.Double ++} ++ ++public final annotation class AFloat : kotlin.Annotation { ++ public constructor AFloat(/*0*/ kotlin.Float) ++ public final val value: kotlin.Float ++} ++ ++public final annotation class AInt : kotlin.Annotation { ++ public constructor AInt(/*0*/ kotlin.Int) ++ public final val value: kotlin.Int ++} ++ ++public final annotation class ALong : kotlin.Annotation { ++ public constructor ALong(/*0*/ kotlin.Long) ++ public final val value: kotlin.Long ++} ++ ++public final annotation class AString : kotlin.Annotation { ++ public constructor AString(/*0*/ kotlin.String) ++ public final val value: kotlin.String ++} ++ ++@test.AString(value = ""Test"") @test.AChar(value = \u0063 ('c')) @test.AInt(value = 10) @test.AByte(value = 11.toByte()) @test.ALong(value = 12.toLong()) @test.ADouble(value = 1.2.toDouble()) @test.AFloat(value = 1.3.toFloat()) public open class AnnotationTrait {",Ditto (`@test.AByte(value = 11.toByte())` vs `@test.AByte(value = 11)`),2017-04-25 10:10:53 +552,"@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtNameReferenceExpression ++import org.jetbrains.kotlin.psi.KtParameter ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS ++import org.jetbrains.kotlin.psi.psiUtil.getPrimaryConstructorParameterWithSameName ++ ++class MakeConstructorParameterPropertyFix(element: KtParameter, private val kotlinValVar: KotlinValVar) : KotlinQuickFixAction(element) { ++ override fun getFamilyName() = ""Make primary constructor parameter a property"" ++ override fun getText() = ""Make primary constructor parameter '${element.name}' a property""","In the case when we're updating an outer class, it'd be better to show the name of that class in the inspection text. +",2016-04-28 09:08:47 +781,"@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.load.java ++ ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.search.DelegatingGlobalSearchScope ++import com.intellij.psi.search.GlobalSearchScope ++import org.jetbrains.kotlin.idea.KotlinFileType ++import javax.inject.Inject ++ ++abstract class AbstractJavaClassFinder : JavaClassFinder { ++ ++ protected lateinit var proj: Project",Please rename to `project`,2017-04-25 08:06:05 +811,"@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.FqName ++import javax.lang.model.type.TypeKind ++import javax.lang.model.type.TypeMirror ++ ++open class SymbolBasedType(val typeMirror: T, ++ val javac: JavacWrapper) : JavaType, JavaAnnotationOwner { ++ ++ companion object { ++ fun create(t: TM, javac: JavacWrapper) = when { ++ t.kind.isPrimitive || t.toString() == ""void"" -> SymbolBasedPrimitiveType(t, javac)",`t.kind.isPrimitive || t.kind == TypeKind.VOID -> ...`,2017-04-25 12:30:40 +770,"@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.FqName ++ ++abstract class JCType(val tree: T, ++ val treePath: TreePath, ++ val javac: JavacWrapper) : JavaType, JavaAnnotationOwner { ++ ++ companion object { ++ fun create(tree: Type, treePath: TreePath, javac: JavacWrapper) = when (tree) { ++ is JCTree.JCPrimitiveTypeTree -> JCPrimitiveType(tree, TreePath(treePath, tree), javac) ++ is JCTree.JCArrayTypeTree -> JCArrayType(tree, TreePath(treePath, tree), javac) ++ is JCTree.JCWildcard -> JCWildcardType(tree, TreePath(treePath, tree), javac) ++ is JCTree.JCTypeApply -> JCClassifierTypeWithTypeArgument(tree, TreePath(treePath, tree), javac) ++ is JCTree.JCExpression -> JCClassifierType(tree, TreePath(treePath, tree), javac) ++ else -> throw UnsupportedOperationException(""Unsupported type: $tree"") ++ } ++ } ++ ++ override val annotations ++ get() = emptyList()",Are you sure this list should be empty? In `JavaTypeImpl` it's not so,2017-04-20 10:03:55 +789,"@@ -0,0 +1,55 @@ ++package test ++ ++public final annotation class AByte : kotlin.Annotation { ++ public constructor AByte(/*0*/ kotlin.Byte) ++ public final val value: kotlin.Byte ++} ++ ++public final annotation class AChar : kotlin.Annotation { ++ public constructor AChar(/*0*/ kotlin.Char) ++ public final val value: kotlin.Char ++} ++ ++public final annotation class ADouble : kotlin.Annotation { ++ public constructor ADouble(/*0*/ kotlin.Double) ++ public final val value: kotlin.Double ++} ++ ++public final annotation class AFloat : kotlin.Annotation { ++ public constructor AFloat(/*0*/ kotlin.Float) ++ public final val value: kotlin.Float ++} ++ ++public final annotation class AInt : kotlin.Annotation { ++ public constructor AInt(/*0*/ kotlin.Int) ++ public final val value: kotlin.Int ++} ++ ++public final annotation class ALong : kotlin.Annotation { ++ public constructor ALong(/*0*/ kotlin.Long) ++ public final val value: kotlin.Long ++} ++ ++public final annotation class AString : kotlin.Annotation { ++ public constructor AString(/*0*/ kotlin.String) ++ public final val value: kotlin.String ++} ++ ++@test.AString(value = ""Test"") @test.AChar(value = \u0063 ('c')) @test.AInt(value = 10) @test.AByte(value = 11.toByte()) @test.ALong(value = 12.toLong()) @test.ADouble(value = 1.2.toDouble()) @test.AFloat(value = 1.3.toFloat()) public open class AnnotationClass {","Why is there `@test.AByte(value = 11.toByte())`, but only `@test.AByte(value = 11)` in the main test data, is worth investigating, I think. Loading annotation arguments with different types than what is done now might break some invariants in the compiler",2017-04-25 10:10:17 +112,"@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ val conditionText = when (element) { ++ is JetIfExpression -> ""if"" ++ is JetWhileExpression -> ""while"" ++ is JetDoWhileExpression -> ""do...while"" ++ is JetForExpression -> ""for"" ++ else -> return false ++ } ++ val jetBlockElement = element.findBlockInExpression(element)","Obviously, won't work for `else` +",2014-02-21 16:37:14 +113,"@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ val conditionText = when (element) { ++ is JetIfExpression -> ""if"" ++ is JetWhileExpression -> ""while"" ++ is JetDoWhileExpression -> ""do...while"" ++ is JetForExpression -> ""for"" ++ else -> return false ++ } ++ val jetBlockElement = element.findBlockInExpression(element) ++ if (jetBlockElement != null) return false ++ ++ setText(""Add braces to '$conditionText' statement"") ++ return true ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val bodyElement = when (element) {","""bodyNode"" would be a better name +",2014-02-21 16:37:24 +114,"@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ val conditionText = when (element) { ++ is JetIfExpression -> ""if"" ++ is JetWhileExpression -> ""while"" ++ is JetDoWhileExpression -> ""do...while"" ++ is JetForExpression -> ""for"" ++ else -> return false ++ } ++ val jetBlockElement = element.findBlockInExpression(element) ++ if (jetBlockElement != null) return false ++ ++ setText(""Add braces to '$conditionText' statement"") ++ return true ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val bodyElement = when (element) { ++ is JetIfExpression -> element.getNode().findChildByType(JetNodeTypes.THEN) ++ else -> element.getNode().findChildByType(JetNodeTypes.BODY) ++ } ++ val bodyText = bodyElement?.getText() ++ val newElement = bodyElement?.getPsi()?.getPrevSibling()?.replace(JetPsiFactory.createExpression(element.getProject(), ""{\n $bodyText \n}""))","You are replace element before expression with block, and then add whitespace. Why not replace expression with block directly? Also, this works incorrectly for `if (true)println()` +",2014-02-21 16:37:56 +115,"@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ val conditionText = when (element) { ++ is JetIfExpression -> ""if"" ++ is JetWhileExpression -> ""while"" ++ is JetDoWhileExpression -> ""do...while"" ++ is JetForExpression -> ""for"" ++ else -> return false ++ } ++ val jetBlockElement = element.findBlockInExpression(element) ++ if (jetBlockElement != null) return false ++ ++ setText(""Add braces to '$conditionText' statement"") ++ return true ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val bodyElement = when (element) { ++ is JetIfExpression -> element.getNode().findChildByType(JetNodeTypes.THEN) ++ else -> element.getNode().findChildByType(JetNodeTypes.BODY) ++ } ++ val bodyText = bodyElement?.getText() ++ val newElement = bodyElement?.getPsi()?.getPrevSibling()?.replace(JetPsiFactory.createExpression(element.getProject(), ""{\n $bodyText \n}"")) ++ newElement?.getParent()?.addBefore(JetPsiFactory.createWhiteSpace(element.getProject()), newElement) ++ bodyElement?.getPsi()?.delete()","Am I right that this sequence of safe calls is only because bodyElement can be null? Shouldn't it be checked in `isApplicable`? Otherwise there can be case when intention is available i UI, but will have no effect, which is confusing. +Side note: if some condition is to hard to check in isApplicable, it's a good idea to show error message. +",2014-02-21 16:38:23 +116,"@@ -0,0 +1,57 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++ ++ ++public class RemoveBracesIntention : JetSelfTargetingIntention(""remove.braces"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ val conditionText = when (element) { ++ is JetIfExpression -> ""if"" ++ is JetWhileExpression -> ""while"" ++ is JetDoWhileExpression -> ""do...while"" ++ is JetForExpression -> ""for"" ++ else -> return false ++ }","Duplicate code. +",2014-02-21 16:39:03 +117,"@@ -0,0 +1,57 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++ ++ ++public class RemoveBracesIntention : JetSelfTargetingIntention(""remove.braces"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ val conditionText = when (element) { ++ is JetIfExpression -> ""if"" ++ is JetWhileExpression -> ""while"" ++ is JetDoWhileExpression -> ""do...while"" ++ is JetForExpression -> ""for"" ++ else -> return false ++ } ++ val jetBlockElement = element.findBlockInExpression(element) ++ if (jetBlockElement == null) return false ++ ++ if (jetBlockElement.getStatements().size == 1) { ++ setText(""Remove braces from '$conditionText' statement"") ++ return true ++ } ++ return false ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val jetBlockElement = element.findBlockInExpression(element) ++ val newElement = jetBlockElement?.replace(JetPsiFactory.createExpression(element.getProject(), jetBlockElement?.getStatements()?.first?.getText()))","Safe call is redundant: we already checked for null in `isApplicable`. +",2014-02-21 16:39:17 +118,"@@ -0,0 +1,57 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++ ++ ++public class RemoveBracesIntention : JetSelfTargetingIntention(""remove.braces"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ val conditionText = when (element) { ++ is JetIfExpression -> ""if"" ++ is JetWhileExpression -> ""while"" ++ is JetDoWhileExpression -> ""do...while"" ++ is JetForExpression -> ""for"" ++ else -> return false ++ } ++ val jetBlockElement = element.findBlockInExpression(element) ++ if (jetBlockElement == null) return false ++ ++ if (jetBlockElement.getStatements().size == 1) { ++ setText(""Remove braces from '$conditionText' statement"") ++ return true ++ } ++ return false ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val jetBlockElement = element.findBlockInExpression(element) ++ val newElement = jetBlockElement?.replace(JetPsiFactory.createExpression(element.getProject(), jetBlockElement?.getStatements()?.first?.getText())) ++ if (element is JetDoWhileExpression) { ++ newElement?.getParent()?.addAfter(JetPsiFactory.createNewLine(element.getProject()), newElement) ++ }","Redundant safe calls again +",2014-02-21 16:39:25 +418,"@@ -0,0 +1,58 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi ++ ++import java.rmi.Remote ++import java.rmi.RemoteException ++ ++public interface CompileService : Remote { ++ ++ public enum class OutputFormat : java.io.Serializable { ++ PLAIN, ++ XML ++ } ++ ++ public interface RemoteIncrementalCache : Remote { ++ throws(RemoteException::class)","Do we really need all those `throws` annotations? +",2015-08-20 13:36:25 +938,"@@ -0,0 +1,58 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiNameIdentifierOwner ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.idea.core.deleteElementAndCleanParent ++import org.jetbrains.kotlin.psi.KtDeclaration ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtProperty ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType ++ ++/**",Please don't add `@author` tags to the code,2017-08-03 09:55:21 +939,"@@ -0,0 +1,58 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiNameIdentifierOwner ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.idea.core.deleteElementAndCleanParent ++import org.jetbrains.kotlin.psi.KtDeclaration ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtProperty ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType ++ ++/** ++ * @author Andrius Semionovas ++ * @since 2017-07-31 ++ */ ++class ReplaceInitializerWithGetterFix(element: KtProperty): KotlinQuickFixAction(element) {",We already have `ConvertPropertyInitializerToGetterIntention` which is offered as an intention action in this context; you should be able to reuse it directly.,2017-08-03 10:00:57 +807,"@@ -0,0 +1,58 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaMember ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.Element ++import javax.lang.model.element.TypeElement ++ ++abstract class SymbolBasedMember(element: T, ++ javac: JavacWrapper) : SymbolBasedElement(element, javac), JavaMember { ++ ++ override val containingClass ++ get() = SymbolBasedClass((element.enclosingElement as TypeElement), javac) ++ ++ override val annotations ++ get() = element.annotationMirrors ++ .map { SymbolBasedAnnotation(it, javac) } ++ ++ override fun findAnnotation(fqName: FqName) = element.annotationMirrors ++ .find { it.toString() == ""@${fqName.asString()}"" }","Please deduplicate this with `SymbolBasedClassifier.findAnnotation`, `SymbolBasedValueParameter.findAnnotation`, `SymbolBasedType.findAnnotation`",2017-04-25 12:24:08 +865,"@@ -0,0 +1,59 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.psi.KtAnnotationEntry ++import org.jetbrains.kotlin.psi.KtCallableDeclaration ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++ ++class MoveReceiverAnnotationFix(element: KtAnnotationEntry) : KotlinQuickFixAction(element) { ++ ++ override fun getFamilyName() = ""Move annotation to receiver type"" ++ override fun getText() = familyName ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val element = element ?: return ++ ++ val declaration = element.getParentOfType(true) ?: return ++ val receiverTypeRef = declaration.receiverTypeReference ?: return ++ ++ receiverTypeRef.addAnnotationEntry(element) ++ element.delete() ++ } ++ ++ companion object Factory : KotlinSingleIntentionActionFactory() { ++ override fun createAction(diagnostic: Diagnostic): IntentionAction? { ++ val diag = Errors.INAPPLICABLE_RECEIVER_TARGET.cast(diagnostic) ++ val entry = diag.psiElement as? KtAnnotationEntry ?: return null ++ ++ val declaration = entry.getParentOfType(true) ?: return null ++ if (declaration.receiverTypeReference == null) return null ++ ++ return MoveReceiverAnnotationFix(entry) ++ } ++ } ++} ++ ++fun String.foo() {",Looks like not-deleted trash. I'll remove it.,2017-05-30 12:43:08 +759,"@@ -0,0 +1,59 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.name.Name ++ ++class JCMethod(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: JavacWrapper) : JCMember(tree, treePath, containingClass, javac), JavaMethod { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract",What about interface members? (not sure it's important),2017-04-11 10:25:49 +554,"@@ -0,0 +1,6 @@ ++// ""Add 'run' before the lambda expression"" ""true"" ++// ERROR: Unresolved reference: run","You can add WITH_RUNTIME directive so that the `run` function will be resolved correctly. +",2016-05-06 15:32:01 +908,"@@ -0,0 +1,6 @@ ++// ""Remove useless is check"" ""false"" ++fun foo(a: String) { ++ when (1) { ++ is Int -> { }","Well, it's an exceptional case but here we can also do something :). If a condition in when branch is definitely true, we can replace the condition with `else` and delete all subsequent branches because they are unreachable anyway. If the condition is definitely false (add test for this case), we can delete this when branch.",2017-07-18 11:04:58 +648,"@@ -0,0 +1,6 @@ ++// WITH_RUNTIME ++// IS_APPLICABLE: true ++ ++fun Int.foo() { ++ +1","This transformation does not look correct for me. I would expect `this + 1` as a result here, +",2016-11-07 09:19:00 +214,"@@ -0,0 +1,6 @@ ++//ERROR: Unresolved reference: SortedMap ++fun a(b: SortedMap) { ++ for ((index, c) in b.withIndices()) {","I'm not sure what's happening here because `SortedMap` is not an iterable/stream/array, so it doesn't have `withIndices` extension and the intention should not be applicable on it as well as on `Map` +",2014-04-30 18:41:11 +614,"@@ -0,0 +1,6 @@ ++public class Foo { ++ private native final void nativeMethod()","Please avoid irrelevant syntax errors in testdata. Java does require semicolons :) +",2016-09-22 10:46:28 +746,"@@ -0,0 +1,60 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.Name ++ ++class JCMethod(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaMethod { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString())",This can be extracted into `JCMember`,2017-04-05 16:09:38 +747,"@@ -0,0 +1,60 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.Name ++ ++class JCMethod(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaMethod { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract","Non-static methods in interface are `abstract` by default. However in Java 1.8+ they are not abstract if `default` modifier exists. Here we have complex logic, so be accurate, please.",2017-04-05 16:10:50 +748,"@@ -0,0 +1,60 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.Name ++ ++class JCMethod(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaMethod { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal",I think interface methods are never `final`,2017-04-05 16:13:37 +745,"@@ -0,0 +1,60 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.load.java.structure.JavaType ++import org.jetbrains.kotlin.name.Name ++ ++class JCMethod(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: Javac) : JCMember(tree, treePath, containingClass, javac), JavaMethod { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = tree.modifiers.isStatic ++ ++ override val isFinal ++ get() = tree.modifiers.isFinal ++ ++ override val visibility",This can be extracted into `JCMember`,2017-04-05 16:08:46 +548,"@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.codeInsight.intention.LowPriorityAction ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.project.ProjectStructureUtil ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.idea.util.findAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.* ++ ++private val annotationFqName = FqName(""kotlin.jvm.JvmOverloads"") ++ ++class AddJvmOverloadsIntention : SelfTargetingIntention( ++ KtParameterList::class.java, ""Add '@JvmOverloads' annotation""","I think that all intentions that modify the declaration of a function need to be available on the function name. Showing this only on the parameter list is confusing +",2016-04-28 08:47:01 +549,"@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.codeInsight.intention.LowPriorityAction ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.project.ProjectStructureUtil ++import org.jetbrains.kotlin.idea.util.addAnnotation ++import org.jetbrains.kotlin.idea.util.findAnnotation ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.* ++ ++private val annotationFqName = FqName(""kotlin.jvm.JvmOverloads"") ++ ++class AddJvmOverloadsIntention : SelfTargetingIntention( ++ KtParameterList::class.java, ""Add '@JvmOverloads' annotation"" ++), LowPriorityAction { ++ ++ override fun isApplicableTo(element: KtParameterList, caretOffset: Int): Boolean { ++ val parent = element.parent as? KtModifierListOwner ?: return false ++ val target = when (parent) { ++ is KtNamedFunction -> ""function '${parent.name}'"" ++ is KtPrimaryConstructor -> ""primary constructor"" ++ is KtSecondaryConstructor -> ""secondary constructor"" ++ else -> return false ++ } ++ text = ""Add '@JvmOverloads' annotation to $target"" ++ ++ return !ProjectStructureUtil.isJsKotlinModule(element.getContainingKtFile())","If a constructor has one parameter with a default value, adding @JvmOverloads won't modify the resulting bytecode in any way, so the intention shouldn't be displayed. +",2016-04-28 08:47:42 +910,"@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.LocalQuickFix ++import com.intellij.codeInspection.ProblemDescriptor ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.KtWhenExpression ++import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression ++ ++class WhenWithOnlyElseInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitWhenExpression(expression: KtWhenExpression) { ++ super.visitWhenExpression(expression)",You don't actually need the `super` call here.,2017-07-24 12:39:59 +911,"@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.LocalQuickFix ++import com.intellij.codeInspection.ProblemDescriptor ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.KtWhenExpression ++import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression ++ ++class WhenWithOnlyElseInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitWhenExpression(expression: KtWhenExpression) { ++ super.visitWhenExpression(expression) ++ ++ val singleEntry = expression.entries.singleOrNull() ++ if (singleEntry?.isElse != true) return ++ ++ val usedAsExpression = expression.isUsedAsExpression(expression.analyze()) ++ ++ holder.registerProblem(expression, ++ ""'when' has only 'else' branch and can be simplified"", ++ SimplifyFix(usedAsExpression) ++ ) ++ } ++ } ++ } ++ ++ private class SimplifyFix( ++ private val isUsedAsExpression: Boolean ++ ) : LocalQuickFix { ++ override fun getFamilyName() = name ++ ++ override fun getName() = ""Simplify expression"" ++ ++ override fun applyFix(project: Project, descriptor: ProblemDescriptor) { ++ val whenExpression = descriptor.psiElement as? KtWhenExpression ?: return",Please don't forget `FileModificationService.getInstance().preparePsiElementForWrite()`,2017-07-24 12:42:50 +799,"@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.JavaVisibilities ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.* ++ ++val Element.isAbstract",Please mark such declarations as `internal` (those that are only used from this module). Also in the other `utils.kt`,2017-04-25 11:51:32 +798,"@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.JavaVisibilities ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.* ++ ++val Element.isAbstract ++ get() = modifiers.contains(Modifier.ABSTRACT) ++ ++val Element.isStatic ++ get() = modifiers.contains(Modifier.STATIC) ++ ++val Element.isFinal ++ get() = modifiers.contains(Modifier.FINAL) ++ ++fun Element.getVisibility() = when { ++ Modifier.PUBLIC in modifiers -> Visibilities.PUBLIC ++ Modifier.PRIVATE in modifiers -> Visibilities.PRIVATE ++ Modifier.PROTECTED in modifiers -> { ++ if (Modifier.STATIC in modifiers) { ++ JavaVisibilities.PROTECTED_STATIC_VISIBILITY ++ } ++ else { ++ JavaVisibilities.PROTECTED_AND_PACKAGE ++ } ++ } ++ else -> JavaVisibilities.PACKAGE_VISIBILITY ++} ++ ++fun TypeElement.computeClassId(): ClassId? { ++ if (enclosingElement.kind != ElementKind.PACKAGE) { ++ val parentClassId = (enclosingElement as TypeElement).computeClassId() ?: return null ++ return parentClassId.createNestedClassId(Name.identifier(simpleName.toString())) ++ } ++ ++ return ClassId.topLevel(FqName(qualifiedName.toString())) ++} ++ ++fun ExecutableElement.valueParameters(javac: JavacWrapper) = parameters.mapIndexed { index, it -> ++ SymbolBasedValueParameter(it, it.simpleName.toString(), (index == parameters.size - 1) && isVarArgs, javac)",`index == parameters.lastIndex`,2017-04-25 11:49:57 +619,"@@ -0,0 +1,63 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions.copyConcatenatedStringToClipboard ++ ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++ ++class ConcatenatedStringGenerator { ++ fun create(element: KtBinaryExpression): String { ++ val binaryExpression = getBinaryParentExpression(element) ++ val stringBuilder = StringBuilder() ++ create(binaryExpression, stringBuilder) ++ return stringBuilder.toString() ++ } ++ ++ private fun getBinaryParentExpression(element: KtBinaryExpression): KtBinaryExpression { ++ var binaryExpression = element.getStrictParentOfType() ?: return element","There is `getTopmostParentOfTypes`, I think it should work here +",2016-09-22 10:56:09 +620,"@@ -0,0 +1,63 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions.copyConcatenatedStringToClipboard ++ ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++ ++class ConcatenatedStringGenerator { ++ fun create(element: KtBinaryExpression): String { ++ val binaryExpression = getBinaryParentExpression(element) ++ val stringBuilder = StringBuilder() ++ create(binaryExpression, stringBuilder) ++ return stringBuilder.toString() ++ } ++ ++ private fun getBinaryParentExpression(element: KtBinaryExpression): KtBinaryExpression { ++ var binaryExpression = element.getStrictParentOfType() ?: return element ++ while (binaryExpression != null) { ++ binaryExpression = binaryExpression.getStrictParentOfType() ?: return element ++ } ++ return element ++ } ++ ++ private fun create(element: KtBinaryExpression, sb: StringBuilder) {","I'd declare it as something like `private fun KtBinaryExpression.appendTo(sb: StringBuilder)`. And the same for the next function. +",2016-09-22 10:57:32 +839,"@@ -0,0 +1,63 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.IntentionWrapper ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.descriptors.ClassDescriptor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.intentions.AddNamesToCallArgumentsIntention ++import org.jetbrains.kotlin.psi.KtCallExpression ++import org.jetbrains.kotlin.psi.KtNameReferenceExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.referenceExpression ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++ ++class CopyWithoutNamedArgumentsInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitCallExpression(expression: KtCallExpression) { ++ super.visitCallExpression(expression) ++ ++ val reference = expression.referenceExpression() as? KtNameReferenceExpression ?: return ++ if (reference.getReferencedNameAsName() != DataClassDescriptorResolver.COPY_METHOD_NAME) return ++ if (expression.valueArguments.none { !it.isNamed() }) return",`.all { it.isNamed() }` is easier to read.,2017-05-03 09:47:04 +360,"@@ -0,0 +1,64 @@ ++# Enums ++ ++Goals: ++* Better syntax for passing constructor parameters when defining enum constants ++* Resolve issues with annotation syntax for enum constants ++ ++## Example ++ ++Simple enum: ++``` kotlin ++enum class Foo { ++ A ++ B ++ C { ++ override fun foo() { ... } ++ } ++ ++ open fun foo() {} ++} ++``` ++ ++Enum with constructor: ++``` kotlin ++enum class Foo(val s: String) { ++ A(""a"") ++ B(""b"") ++ C(""c"") { ++ override fun foo() { ... } ++ } ++ ++ open fun foo() {} ++} ++``` ++ ++Issues ++* Enum literals syntax clash with annotation syntax ++ * Option 1.1: Forbid short annotation syntax in enums. **downside**: cannot annotate functions/properties/classes in this enum ++ * Option 1.2: Add a separator between enum constants and members, and forbid short annotation syntax only on enum entriesc themselves. **downside**: separator is not intuitive, hard to think of when doign this for the first time (the error message will be rather clear and instructive, though)","Spelling: doign -> doing +",2015-04-04 17:52:45 +372,"@@ -0,0 +1,64 @@ ++# Enums ++ ++Goals: ++* Better syntax for passing constructor parameters when defining enum constants ++* Resolve issues with annotation syntax for enum constants ++ ++## Example ++ ++Simple enum: ++``` kotlin ++enum class Foo { ++ A ++ B ++ C { ++ override fun foo() { ... } ++ } ++ ++ open fun foo() {} ++} ++``` ++ ++Enum with constructor: ++``` kotlin ++enum class Foo(val s: String) { ++ A(""a"") ++ B(""b"") ++ C(""c"") { ++ override fun foo() { ... } ++ } ++ ++ open fun foo() {} ++} ++``` ++ ++Issues ++* Enum literals syntax clash with annotation syntax ++ * Option 1.1: Forbid short annotation syntax in enums. **downside**: cannot annotate functions/properties/classes in this enum ++ * Option 1.2: Add a separator between enum constants and members, and forbid short annotation syntax only on enum entriesc themselves. **downside**: separator is not intuitive, hard to think of when doing this for the first time (the error message will be rather clear and instructive, though) ++ * Option 1.3: prefix each entry with a soft-keyword, e.g. `entry`. **downside**: verbosity ++* How do we specify other supertypes for a constant (if any) ++ * Option 2.1: Leave unsupported, use cases are very few, and Java does not support it ++ * Option 2.2: `A(""s""): OtherType` ++ ++Example for option 1.2: ++ ++``` kotlin ++enum class Foo(val s: String) { ++ A(""a"") // semicolon CAN NOT be used here! ++ B(""b"") ++ C(""c"") { ++ override fun foo() { ... } ++ }; // semicolon is MANDATORY here, if a member follows ++ ++ // if no semicolon was provided, `open` is another enum entry ++ open fun foo() {} ++} ++``` ++ ++Notes: ++* No overhead in the most common case of no members at all: `enum class E {A B C}","Missing backtick? +",2015-04-06 17:37:57 +25,"@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.openapi.vfs.LocalFileSystem; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.testFramework.PsiTestUtil; ++import org.jetbrains.jet.JetTestCaseBuilder; ++ ++import java.util.Arrays; ++import java.util.List; ++ ++public class FinalJavaSupertypeTest extends JetQuickFixMultiFileTest { ++ @Override ++ protected void setUp() throws Exception { ++ super.setUp(); ++ ++ String path = getTestDataPath(); ++ VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); ++ if (virtualFile != null) { ++ virtualFile.getChildren(); ++ virtualFile.refresh(false, true); ++ }","This piece of code occurs at least three times in the code base, it probably means that we should create a utility method for it. +",2013-01-29 14:05:29 +26,"@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.openapi.vfs.LocalFileSystem; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiDocumentManager; ++import com.intellij.testFramework.PsiTestUtil; ++import org.jetbrains.jet.JetTestCaseBuilder; ++ ++import java.util.Arrays; ++import java.util.List; ++ ++public class FinalJavaSupertypeTest extends JetQuickFixMultiFileTest { ++ @Override ++ protected void setUp() throws Exception { ++ super.setUp(); ++ ++ String path = getTestDataPath(); ++ VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); ++ if (virtualFile != null) { ++ virtualFile.getChildren(); ++ virtualFile.refresh(false, true); ++ } ++ } ++ ++ public void testFinalJavaSupertype() throws Exception { ++ String path = getTestDataPath() + ""/../javaCode/""; ++ final VirtualFile rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, path, myFilesToDelete, false); ++ addSourceContentToRoots(myModule, rootDir); ++ PsiDocumentManager.getInstance(myProject).commitAllDocuments(); ++ doTest(); ++ } ++ ++ @Override ++ protected String getCheckFileName() { ++ assert false;","It's a lot better to explicitly throw an exception here + provide a comprehensible message that tells me why this behavior is not legitimate +",2013-01-29 14:09:34 +562,"@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.psi.* ++ ++class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ val patterns = mapOf( ++ ""System.out.println($0)"" to ""println($0)"", ++ ""System.out.print($0)"" to ""print($0)"", ++ ""Collections.sort($0)"" to ""$0.sort()"" ++ ) ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitQualifiedExpression(expression: KtQualifiedExpression) { ++ super.visitQualifiedExpression(expression) ++ ++ val selectorExpression = expression.selectorExpression ?: return ++ if (selectorExpression !is KtCallExpression) return ++ if (selectorExpression.valueArguments.size != 1) return ++ val value = selectorExpression.valueArguments[0].text ++ val pattern = expression.text.replace(value, ""$0"")","This is not good enough. You need to resolve the call to make sure that it points to the correct method, and not to a method of a different class that also happens to be called `Collections`. +",2016-05-18 13:25:07 +563,"@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.psi.* ++ ++class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ val patterns = mapOf( ++ ""System.out.println($0)"" to ""println($0)"", ++ ""System.out.print($0)"" to ""print($0)"", ++ ""Collections.sort($0)"" to ""$0.sort()"" ++ ) ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitQualifiedExpression(expression: KtQualifiedExpression) { ++ super.visitQualifiedExpression(expression) ++ ++ val selectorExpression = expression.selectorExpression ?: return ++ if (selectorExpression !is KtCallExpression) return ++ if (selectorExpression.valueArguments.size != 1) return ++ val value = selectorExpression.valueArguments[0].text ++ val pattern = expression.text.replace(value, ""$0"") ++ if (!patterns.containsKey(pattern)) return ++ ++ holder.registerProblem(expression, ++ ""Unnecessary java usage"", ++ ProblemHighlightType.LIKE_UNUSED_SYMBOL,","LIKE_UNUSED_SYMBOL highlighting is applied to code fragments that can be removed entirely. In this case, the quick fix is not removing the code, but is replacing it with different code. +",2016-05-18 13:25:59 +953,"@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.codeInsight.intention.LowPriorityAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.idea.core.moveCaret ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.createExpressionByPattern ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull ++ ++class SwapStringEqualsIgnoreCaseIntention : SelfTargetingRangeIntention(KtDotQualifiedExpression::class.java, ""Flip 'equals'""), LowPriorityAction { ++ ++ override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? { ++ val descriptor = element.getCallableDescriptor() ?: return null ++ ++ val fqName: FqName = descriptor.fqNameOrNull() ?: return null ++ if (fqName.asString() != ""kotlin.text.equals"") return null ++ ++ val valueParameters = descriptor.valueParameters.takeIf { it.size == 2 } ?: return null ++ if (!KotlinBuiltIns.isStringOrNullableString(valueParameters[0].type)) return null ++ if (!KotlinBuiltIns.isBoolean(valueParameters[1].type)) return null ++ ++ return element.callExpression?.calleeExpression?.textRange ++ } ++ ++ override fun applyTo(element: KtDotQualifiedExpression, editor: Editor?) { ++ val callExpression = element.callExpression ?: return ++ val offset = (editor?.caretModel?.offset ?: 0) - (callExpression.calleeExpression?.startOffset ?: 0) ++ val receiverExpression = element.receiverExpression ++ val valueArguments = callExpression.valueArguments.takeIf { it.size == 2 } ?: return ++ val newElement = KtPsiFactory(element).createExpressionByPattern( ++ ""$0.equals($1, $2)"", ++ valueArguments[0].text,",It's better to use here expressions and not their text,2017-08-07 11:06:09 +896,"@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.kotlin.lexer.KtTokens.* ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class ConvertClassToSealedClassIntention : SelfTargetingRangeIntention(KtClass::class.java, ""Convert to sealed class"") { ++ ++ override fun applicabilityRange(element: KtClass): TextRange? { ++ if (element.modifierList == null) return null ++ if (!element.hasModifier(OPEN_KEYWORD) && !element.hasModifier(ABSTRACT_KEYWORD)) return null ++ ++ val constructors = listOfNotNull(element.primaryConstructor) + element.secondaryConstructors ++ if (constructors.isEmpty()) return null ++ if (constructors.any { !it.hasModifier(PRIVATE_KEYWORD) }) return null",Please use `none` instead of `any` with a negative condition.,2017-07-17 11:14:05 +898,"@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.kotlin.lexer.KtTokens.* ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class ConvertClassToSealedClassIntention : SelfTargetingRangeIntention(KtClass::class.java, ""Convert to sealed class"") { ++ ++ override fun applicabilityRange(element: KtClass): TextRange? { ++ if (element.modifierList == null) return null ++ if (!element.hasModifier(OPEN_KEYWORD) && !element.hasModifier(ABSTRACT_KEYWORD)) return null ++ ++ val constructors = listOfNotNull(element.primaryConstructor) + element.secondaryConstructors ++ if (constructors.isEmpty()) return null ++ if (constructors.any { !it.hasModifier(PRIVATE_KEYWORD) }) return null ++ ++ val nameIdentifier = element.nameIdentifier ?: return null ++ return TextRange(element.startOffset, nameIdentifier.endOffset) ++ } ++ ++ override fun applyTo(element: KtClass, editor: Editor?) { ++ val newElement = element.copy() as KtClass",It doesn't seem necessary to create a copy; you should be able to apply all the changes to the original `KtClass` directly.,2017-07-17 11:15:07 +897,"@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.kotlin.lexer.KtTokens.* ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class ConvertClassToSealedClassIntention : SelfTargetingRangeIntention(KtClass::class.java, ""Convert to sealed class"") { ++ ++ override fun applicabilityRange(element: KtClass): TextRange? { ++ if (element.modifierList == null) return null ++ if (!element.hasModifier(OPEN_KEYWORD) && !element.hasModifier(ABSTRACT_KEYWORD)) return null ++ ++ val constructors = listOfNotNull(element.primaryConstructor) + element.secondaryConstructors ++ if (constructors.isEmpty()) return null ++ if (constructors.any { !it.hasModifier(PRIVATE_KEYWORD) }) return null ++ ++ val nameIdentifier = element.nameIdentifier ?: return null ++ return TextRange(element.startOffset, nameIdentifier.endOffset) ++ } ++ ++ override fun applyTo(element: KtClass, editor: Editor?) { ++ val newElement = element.copy() as KtClass ++ ++ newElement.modifierList?.run { ++ getModifier(OPEN_KEYWORD)?.delete() ++ getModifier(ABSTRACT_KEYWORD)?.delete() ++ newElement.addModifier(SEALED_KEYWORD)",It's better to move this line out of the `run` block.,2017-07-17 11:14:40 +899,"@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.kotlin.lexer.KtTokens.* ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class ConvertClassToSealedClassIntention : SelfTargetingRangeIntention(KtClass::class.java, ""Convert to sealed class"") { ++ ++ override fun applicabilityRange(element: KtClass): TextRange? { ++ if (element.modifierList == null) return null ++ if (!element.hasModifier(OPEN_KEYWORD) && !element.hasModifier(ABSTRACT_KEYWORD)) return null ++ ++ val constructors = listOfNotNull(element.primaryConstructor) + element.secondaryConstructors ++ if (constructors.isEmpty()) return null ++ if (constructors.any { !it.hasModifier(PRIVATE_KEYWORD) }) return null ++ ++ val nameIdentifier = element.nameIdentifier ?: return null ++ return TextRange(element.startOffset, nameIdentifier.endOffset) ++ } ++ ++ override fun applyTo(element: KtClass, editor: Editor?) { ++ val newElement = element.copy() as KtClass ++ ++ newElement.modifierList?.run { ++ getModifier(OPEN_KEYWORD)?.delete() ++ getModifier(ABSTRACT_KEYWORD)?.delete() ++ newElement.addModifier(SEALED_KEYWORD) ++ } ++ ++ newElement.primaryConstructor?.run { ++ modifierList?.getModifier(PRIVATE_KEYWORD)?.delete() ++ getConstructorKeyword()?.delete()",The `constructor` keyword can only be deleted if there are no annotations or other modifiers on the constructor. Please add a test for the case with annotations.,2017-07-17 11:15:50 +900,"@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiWhiteSpace ++import org.jetbrains.kotlin.lexer.KtTokens.* ++import org.jetbrains.kotlin.psi.KtClass ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++ ++class ConvertClassToSealedClassIntention : SelfTargetingRangeIntention(KtClass::class.java, ""Convert to sealed class"") { ++ ++ override fun applicabilityRange(element: KtClass): TextRange? { ++ if (element.modifierList == null) return null ++ if (!element.hasModifier(OPEN_KEYWORD) && !element.hasModifier(ABSTRACT_KEYWORD)) return null ++ ++ val constructors = listOfNotNull(element.primaryConstructor) + element.secondaryConstructors ++ if (constructors.isEmpty()) return null ++ if (constructors.any { !it.hasModifier(PRIVATE_KEYWORD) }) return null ++ ++ val nameIdentifier = element.nameIdentifier ?: return null ++ return TextRange(element.startOffset, nameIdentifier.endOffset) ++ } ++ ++ override fun applyTo(element: KtClass, editor: Editor?) { ++ val newElement = element.copy() as KtClass ++ ++ newElement.modifierList?.run { ++ getModifier(OPEN_KEYWORD)?.delete() ++ getModifier(ABSTRACT_KEYWORD)?.delete() ++ newElement.addModifier(SEALED_KEYWORD) ++ } ++ ++ newElement.primaryConstructor?.run { ++ modifierList?.getModifier(PRIVATE_KEYWORD)?.delete() ++ getConstructorKeyword()?.delete() ++ if (newElement.secondaryConstructors.isEmpty() && valueParameters.isEmpty()) valueParameterList?.delete() ++ (newElement.nameIdentifier?.prevSibling as? PsiWhiteSpace)?.delete()",It should never be necessary to do that manually; the formatter should take care of whitespaces.,2017-07-17 11:16:15 +817,"@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.javac ++ ++import com.sun.tools.javac.util.Context ++import com.sun.tools.javac.util.Log ++import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity ++import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector ++import org.jetbrains.kotlin.cli.common.messages.MessageCollector ++import java.io.PrintWriter ++import java.io.Writer ++ ++class JavacLogger(context: Context, ++ errorWriter: PrintWriter, ++ warningWriter: PrintWriter, ++ infoWriter: PrintWriter) : Log(context, errorWriter, warningWriter, infoWriter) { ++ init { ++ context.put(Log.outKey, infoWriter) ++ } ++ ++ override fun printLines(kind: WriterKind, message: String, vararg args: Any?) {} ++ ++ companion object { ++ fun preRegister(context: Context, messageCollector: MessageCollector) { ++ context.put(Log.logKey, Context.Factory { ++ JavacLogger(it, ++ PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.ERROR)), ++ PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.WARNING)), ++ PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.INFO))) ++ }) ++ } ++ } ++ ++} ++ ++private class MessageCollectorAdapter(private val messageCollector: MessageCollector, ++ private val severity: CompilerMessageSeverity) : Writer() { ++ ++ override fun write(buffer: CharArray, offset: Int, length: Int) { ++ if (length > 1) {",Why? A comment would be helpful here,2017-04-25 13:06:30 +756,"@@ -0,0 +1,66 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.PropertyDescriptor ++import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluator ++import org.jetbrains.kotlin.load.java.structure.JavaField ++import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory ++import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns ++import org.jetbrains.kotlin.wrappers.symbols.JavacField ++import org.jetbrains.kotlin.wrappers.trees.JCClassifierType ++import org.jetbrains.kotlin.wrappers.trees.JCField ++import org.jetbrains.kotlin.wrappers.trees.JCPrimitiveType ++ ++class JavacBasedPropertyInitializerEvaluator : JavaPropertyInitializerEvaluator { ++ ++ override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor) = when (field) { ++ is JavacField<*> -> field.constant(descriptor) ++ is JCField<*> -> field.constant(descriptor) ++ else -> null ++ } ++ ++ override fun isNotNullCompileTimeConstant(field: JavaField) = when(field) { ++ is JavacField<*> -> field.isCompileTimeConstant() ++ is JCField<*> -> field.isCompileTimeConstant() ++ else -> false ++ } ++ ++ private fun JavacField<*>.constant(descriptor: PropertyDescriptor) = value?.let { ++ ConstantValueFactory(descriptor.builtIns).createConstantValue(it) ++ } ++ ++ private fun JCField<*>.constant(descriptor: PropertyDescriptor) = value?.let { ++ if (isCompileTimeConstant() && it is JCTree.JCLiteral) { ++ ConstantValueFactory(descriptor.builtIns).createConstantValue(it.value) ++ } else null ++ } ++ ++ private fun JavacField<*>.isCompileTimeConstant() = value?.let { ++ val typeMirror = type.typeMirror ++ ++ (typeMirror.kind.isPrimitive || typeMirror.toString() == ""java.lang.String"")","It would be better to avoid `toString()` call here, if possible. Does this `typeMirror` have something like `name` or `fqName`?",2017-04-11 10:16:24 +35,"@@ -0,0 +1,68 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.impl.source.tree.LeafPsiElement; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class RemoveSpreadFix extends JetIntentionAction{ ++ private final LeafPsiElement spreadSign; ++ ++ public RemoveSpreadFix(@NotNull LeafPsiElement element) { ++ super(element); ++ spreadSign = element; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""remove.spread.sign""); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""remove.spread.sign""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ spreadSign.delete(); ++ } ++ ++ public static JetIntentionActionFactory createFactory() { ++ return new JetIntentionActionFactory() { ++ @Override ++ public JetIntentionAction createAction(Diagnostic diagnostic) { ++ PsiElement element = diagnostic.getPsiElement(); ++ if (!(element instanceof LeafPsiElement)) return null;","Almost right, but here's the way to do it without constant: + +``` +if (leaf instanceof LeafPsiElement && ((LeafPsiElement)leaf).getElementType() == JetTokens.MUL) { +} +``` +",2013-02-22 15:53:06 +988,"@@ -0,0 +1,68 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.functors ++ ++import org.jetbrains.kotlin.effectsystem.impls.or ++import org.jetbrains.kotlin.effectsystem.factories.lift ++import org.jetbrains.kotlin.effectsystem.structure.* ++ ++/** ++ * Applies [operation] to [first] and [second] if both not-null, otherwise returns null ++ */ ++internal fun applyIfBothNotNull(first: F?, second: S?, operation: (F, S) -> R): R? = ++ if (first == null || second == null) null else operation(first, second) ++ ++/** ++ * If both [first] and [second] are null, then return null ++ * If only one of [first] and [second] is null, then return other one ++ * Otherwise, return result of [operation] ++ */ ++internal fun applyWithDefault(first: F?, second: S?, operation: (F, S) -> R): R? = when { ++ first == null && second == null -> null ++ first == null -> second ++ second == null -> first ++ else -> operation(first, second) ++} ++ ++internal fun foldConditionsWithOr(list: List): ESBooleanExpression? = ++ if (list.isEmpty()) ++ null ++ else ++ list.map { it.condition }.reduce { acc, condition -> acc.or(condition) } ++ ++/** ++ * Places all clauses that equal to `firstModel` into first list, and all clauses that equal to `secondModel` into second list ++ */ ++internal fun List.strictPartition(firstModel: ESEffect, secondModel: ESEffect): Pair, List> {","May be it's better to return here just lists of conditions, not lists of clauses. Then you can accept list of conditions in `foldConditionsWithOr`.",2017-08-15 17:01:07 +936,"@@ -0,0 +1,68 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtParenthesizedExpression ++import org.jetbrains.kotlin.psi.KtPrefixExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++import org.jetbrains.kotlin.types.typeUtil.isBoolean ++ ++class DoubleNegationInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitPrefixExpression(expression: KtPrefixExpression) { ++ if (expression.operationToken != KtTokens.EXCL || expression.baseExpression?.getType(expression.analyze())?.isBoolean() != true) { ++ return ++ } ++ var parent = expression.parent ++ while (parent is KtParenthesizedExpression) { ++ parent = parent.parent ++ } ++ if (parent is KtPrefixExpression && parent.operationToken == KtTokens.EXCL) { ++ holder.registerProblem(expression, ++ ""Redundant double negation"", ++ ProblemHighlightType.WEAK_WARNING,","For future: use here `GENERIC_ERROR_OR_WARNING` if you want to get highlight type depending on inspection severity level (by default, from plugin.xml, or configured by user). Explicitly given `WEAK_WARNING` enforces this severiry level making it unconfigurable by user (will fix myself).",2017-07-27 08:13:44 +961,"@@ -0,0 +1,68 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.CleanupLocalInspectionTool ++import com.intellij.codeInspection.LocalInspectionToolSession ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import java.util.* ++ ++class SuspiciousEqualsCombination : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (expression.parent is KtBinaryExpression) return ++ val (first, second) = expression.parseBinary() ++ val eqeq = first.map { it.text } ++ val eqeqeq = second.map { it.text } ++ if (eqeq.fold(false) { acc, it -> acc || eqeqeq.contains(it) }) { ++ holder.registerProblem(expression, ""Suspicious combination of == and ==="", ++ ProblemHighlightType.GENERIC_ERROR_OR_WARNING) ++ } ++ } ++ } ++ ++ private fun KtBinaryExpression.parseBinary(pair: Pair, MutableList>","I think the intent of this code will be much clearer if you used an explicit class instead of a Pair: + +``` +data class ComparisonOperands(val eqEqOperands: MutableList, val eqEqEqOperands: MutableList)",2017-08-15 09:49:55 +962,"@@ -0,0 +1,68 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.CleanupLocalInspectionTool ++import com.intellij.codeInspection.LocalInspectionToolSession ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import java.util.* ++ ++class SuspiciousEqualsCombination : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (expression.parent is KtBinaryExpression) return ++ val (first, second) = expression.parseBinary() ++ val eqeq = first.map { it.text } ++ val eqeqeq = second.map { it.text } ++ if (eqeq.fold(false) { acc, it -> acc || eqeqeq.contains(it) }) { ++ holder.registerProblem(expression, ""Suspicious combination of == and ==="", ++ ProblemHighlightType.GENERIC_ERROR_OR_WARNING) ++ } ++ } ++ } ++ ++ private fun KtBinaryExpression.parseBinary(pair: Pair, MutableList> ++ = Pair(LinkedList(), LinkedList())): Pair, MutableList> {",Please don't use `LinkedList` for anything ever. :),2017-08-15 09:50:25 +963,"@@ -0,0 +1,68 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.CleanupLocalInspectionTool ++import com.intellij.codeInspection.LocalInspectionToolSession ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import java.util.* ++ ++class SuspiciousEqualsCombination : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (expression.parent is KtBinaryExpression) return ++ val (first, second) = expression.parseBinary() ++ val eqeq = first.map { it.text } ++ val eqeqeq = second.map { it.text } ++ if (eqeq.fold(false) { acc, it -> acc || eqeqeq.contains(it) }) { ++ holder.registerProblem(expression, ""Suspicious combination of == and ==="", ++ ProblemHighlightType.GENERIC_ERROR_OR_WARNING) ++ } ++ } ++ } ++ ++ private fun KtBinaryExpression.parseBinary(pair: Pair, MutableList> ++ = Pair(LinkedList(), LinkedList())): Pair, MutableList> { ++ when (operationToken) { ++ KtTokens.EQEQ, KtTokens.EXCLEQ -> { ++ left?.let(pair.first::add)","I'd check that the operands are `KtNameReferenceExpression`'s, to make the behavior more predictable.",2017-08-15 09:50:58 +627,"@@ -0,0 +1,69 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection ++import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++import java.util.* ++ ++class RemoveRedundantCallsOfConversionMethodsInspection : IntentionBasedInspection(RemoveRedundantCallsOfConversionMethodsIntention::class)","I think these redundant calls should be highlighted as unused symbols. +",2016-10-07 09:51:22 +628,"@@ -0,0 +1,69 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection ++import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++import java.util.* ++ ++class RemoveRedundantCallsOfConversionMethodsInspection : IntentionBasedInspection(RemoveRedundantCallsOfConversionMethodsIntention::class) ++ ++class RemoveRedundantCallsOfConversionMethodsIntention : SelfTargetingOffsetIndependentIntention(KtDotQualifiedExpression::class.java, ""Remove redundant calls of the conversion method"") { ++ ++ private val targetClassMap = mapOf(""toList()"" to List::class.qualifiedName, ++ ""toSet()"" to Set::class.qualifiedName, ++ ""toMap()"" to Map::class.qualifiedName, ++ ""toMutableList()"" to ""kotlin.collections.MutableList"", ++ ""toMutableSet()"" to ""kotlin.collections.MutableSet"", ++ ""toMutableMap()"" to ""kotlin.collections.MutableMap"", ++ ""toSortedSet()"" to SortedSet::class.qualifiedName, ++ ""toSortedMap()"" to SortedMap::class.qualifiedName, ++ ""toString()"" to String::class.qualifiedName, ++ ""toDouble()"" to Double::class.qualifiedName, ++ ""toFloat()"" to Float::class.qualifiedName, ++ ""toLong()"" to Long::class.qualifiedName, ++ ""toInt()"" to Int::class.qualifiedName, ++ ""toChar()"" to Char::class.qualifiedName, ++ ""toShort()"" to Short::class.qualifiedName, ++ ""toByte()"" to Byte::class.qualifiedName) ++ ++ ++ override fun applyTo(element: KtDotQualifiedExpression, editor: Editor?) { ++ element.replaced(element.receiverExpression) ++ ++ mutableMapOf(1 to 1).toMutableMap()","What is it? Looks like it's not needed here :) +",2016-10-07 09:52:16 +629,"@@ -0,0 +1,69 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection ++import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++import java.util.* ++ ++class RemoveRedundantCallsOfConversionMethodsInspection : IntentionBasedInspection(RemoveRedundantCallsOfConversionMethodsIntention::class) ++ ++class RemoveRedundantCallsOfConversionMethodsIntention : SelfTargetingOffsetIndependentIntention(KtDotQualifiedExpression::class.java, ""Remove redundant calls of the conversion method"") { ++ ++ private val targetClassMap = mapOf(""toList()"" to List::class.qualifiedName, ++ ""toSet()"" to Set::class.qualifiedName, ++ ""toMap()"" to Map::class.qualifiedName, ++ ""toMutableList()"" to ""kotlin.collections.MutableList"", ++ ""toMutableSet()"" to ""kotlin.collections.MutableSet"", ++ ""toMutableMap()"" to ""kotlin.collections.MutableMap"", ++ ""toSortedSet()"" to SortedSet::class.qualifiedName, ++ ""toSortedMap()"" to SortedMap::class.qualifiedName, ++ ""toString()"" to String::class.qualifiedName, ++ ""toDouble()"" to Double::class.qualifiedName, ++ ""toFloat()"" to Float::class.qualifiedName, ++ ""toLong()"" to Long::class.qualifiedName, ++ ""toInt()"" to Int::class.qualifiedName, ++ ""toChar()"" to Char::class.qualifiedName, ++ ""toShort()"" to Short::class.qualifiedName, ++ ""toByte()"" to Byte::class.qualifiedName) ++ ++ ++ override fun applyTo(element: KtDotQualifiedExpression, editor: Editor?) { ++ element.replaced(element.receiverExpression) ++ ++ mutableMapOf(1 to 1).toMutableMap() ++ } ++ ++ override fun isApplicableTo(element: KtDotQualifiedExpression): Boolean {","Looks like we can apply this intention for all qualified expressions, not only unsafe ones. +",2016-10-07 09:53:28 +630,"@@ -0,0 +1,69 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection ++import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtStringTemplateExpression ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++import java.util.* ++ ++class RemoveRedundantCallsOfConversionMethodsInspection : IntentionBasedInspection(RemoveRedundantCallsOfConversionMethodsIntention::class) ++ ++class RemoveRedundantCallsOfConversionMethodsIntention : SelfTargetingOffsetIndependentIntention(KtDotQualifiedExpression::class.java, ""Remove redundant calls of the conversion method"") { ++ ++ private val targetClassMap = mapOf(""toList()"" to List::class.qualifiedName, ++ ""toSet()"" to Set::class.qualifiedName, ++ ""toMap()"" to Map::class.qualifiedName, ++ ""toMutableList()"" to ""kotlin.collections.MutableList"", ++ ""toMutableSet()"" to ""kotlin.collections.MutableSet"", ++ ""toMutableMap()"" to ""kotlin.collections.MutableMap"", ++ ""toSortedSet()"" to SortedSet::class.qualifiedName, ++ ""toSortedMap()"" to SortedMap::class.qualifiedName, ++ ""toString()"" to String::class.qualifiedName, ++ ""toDouble()"" to Double::class.qualifiedName, ++ ""toFloat()"" to Float::class.qualifiedName, ++ ""toLong()"" to Long::class.qualifiedName, ++ ""toInt()"" to Int::class.qualifiedName, ++ ""toChar()"" to Char::class.qualifiedName, ++ ""toShort()"" to Short::class.qualifiedName, ++ ""toByte()"" to Byte::class.qualifiedName) ++ ++ ++ override fun applyTo(element: KtDotQualifiedExpression, editor: Editor?) { ++ element.replaced(element.receiverExpression) ++ ++ mutableMapOf(1 to 1).toMutableMap() ++ } ++ ++ override fun isApplicableTo(element: KtDotQualifiedExpression): Boolean { ++ val selectorExpressionText = element.selectorExpression?.text ++ val qualifiedName = targetClassMap[selectorExpressionText] ?: return false ++ val receiverExpression = element.receiverExpression ++ return when (receiverExpression) { ++ is KtStringTemplateExpression -> String::class.qualifiedName ++ is KtConstantExpression -> receiverExpression.getType(receiverExpression.analyze())?.getJetTypeFqName(false) ++ else -> receiverExpression.getResolvedCall(receiverExpression.analyze())?.candidateDescriptor?.returnType?.getJetTypeFqName(false) ++ } == qualifiedName","I'm not sure here what will be happened if somebody defines custom `toType()` function. Probably it's not too important, because it's expected that `toType()` has result of `Type` anyway. +",2016-10-07 09:59:19 +546,"@@ -0,0 +1,69 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType ++import org.jetbrains.kotlin.builtins.isExtensionFunctionType ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.KtTypeReference ++import org.jetbrains.kotlin.renderer.DescriptorRenderer ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++import org.jetbrains.kotlin.types.KotlinType ++ ++class ConvertExtensionToFunctionTypeFix(element: KtTypeReference, type: KotlinType) : KotlinQuickFixAction(element) { ++ ++ private val targetTypeStringShort = type.renderType(IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES) ++ private val targetTypeStringLong = type.renderType(IdeDescriptorRenderers.SOURCE_CODE) ++ ++ override fun getText() = ""Convert supertype to '$targetTypeStringShort'"" ++ override fun getFamilyName() = ""Convert extension function type to regular function type.""","No period here please +",2016-04-28 08:41:35 +547,"@@ -0,0 +1,69 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType ++import org.jetbrains.kotlin.builtins.isExtensionFunctionType ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.KtTypeReference ++import org.jetbrains.kotlin.renderer.DescriptorRenderer ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++import org.jetbrains.kotlin.types.KotlinType ++ ++class ConvertExtensionToFunctionTypeFix(element: KtTypeReference, type: KotlinType) : KotlinQuickFixAction(element) { ++ ++ private val targetTypeStringShort = type.renderType(IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES) ++ private val targetTypeStringLong = type.renderType(IdeDescriptorRenderers.SOURCE_CODE) ++ ++ override fun getText() = ""Convert supertype to '$targetTypeStringShort'"" ++ override fun getFamilyName() = ""Convert extension function type to regular function type."" ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val replaced = element.replaced(KtPsiFactory(project).createType(targetTypeStringLong)) ++ ShortenReferences.DEFAULT.process(replaced) ++ } ++ ++ private fun KotlinType.renderType(renderer: DescriptorRenderer) = buildString { ++ append('(') ++ arguments.dropLast(1).map { renderer.renderType(it.type) }.joinTo(this@buildString, "", "")","I'd add a test for more than one argument, and/or for type with type parameters +",2016-04-28 08:42:07 +997,"@@ -0,0 +1,69 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.CleanupLocalInspectionTool ++import com.intellij.codeInspection.LocalInspectionToolSession ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++ ++class SuspiciousEqualsCombination : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (expression.parent is KtBinaryExpression) return ++ val operands = expression.parseBinary() ++ val eqeq = operands.eqEqOperands.map { it.text } ++ val eqeqeq = operands.eqEqEqOperands.map { it.text } ++ if (eqeq.fold(false) { acc, it -> acc || eqeqeq.contains(it) }) {",This can actually be expressed as `eqeq.intersect(eqeqeq).isNotEmpty()`,2017-08-16 16:41:17 +940,"@@ -0,0 +1,7 @@ ++// ""Replace initializer with getter"" ""true"" ++ ++fun String.foo() = ""bar"" ++ ++interface A { ++ val name = ""The quick brown fox jumps over the lazy dog"".foo()",Neither the existing intention action nor your suggested quickfix handle `var` properties correctly. They should create a stub for the setter with no implementation.,2017-08-03 10:02:22 +213,"@@ -0,0 +1,7 @@ ++// ERROR: Unresolved reference: listOf ++fun a() { ++ val b = listOf(1,2,3,4,5)","You should use `// WITH_RUNTIME` directive in this and all other tests where you use standard library functions to avoid errors +",2014-04-30 18:18:06 +135,"@@ -0,0 +1,7 @@ ++// IS_APPLICABLE: false ++fun foo() { ++ if (true) { ++ println(""test"") ++ println(""test2"") ++ } ++}","Typo in file name. +",2014-03-04 16:08:30 +347,"@@ -0,0 +1,7 @@ ++class KotlinClass(): JavaClass({}) {","Please make function literal here non-trivial. +",2015-03-26 15:35:16 +163,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ if (hasDeclaredParamsType || hasDeclaredReturnType || hasDeclaredReceiverType) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val paramList = element.getFunctionLiteral().getValueParameterList()","Ditto (`element.getFunctionLiteral()` deserves to be extracted into a variable) +",2014-04-09 15:42:14 +162,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ if (hasDeclaredParamsType || hasDeclaredReturnType || hasDeclaredReceiverType) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val paramList = element.getFunctionLiteral().getValueParameterList() ++ val params = paramList?.getParameters() ++ ++ if (element.hasDeclaredReturnType()) { ++ val childAfterParamList = paramList?.getNextSibling() ++ val arrow = element.getFunctionLiteral().getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ element.getFunctionLiteral().deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ element.getFunctionLiteral().addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ if (hasDeclaredReceiverType) { ++ val childAfterBrace = element.getFunctionLiteral().getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = paramList?.getPrevSibling() ++ element.getFunctionLiteral().deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ if (params != null && params!!.size() == 1 && params[0].getNameIdentifier() != null) {","There's a warning about a useless `!!` here +",2014-04-09 15:41:34 +164,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.types.ErrorUtils ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ if (hasDeclaredParamsType || hasDeclaredReturnType || hasDeclaredReceiverType) return true ++ ++ return false ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val paramList = element.getFunctionLiteral().getValueParameterList() ++ val params = paramList?.getParameters() ++ ++ if (element.hasDeclaredReturnType()) { ++ val childAfterParamList = paramList?.getNextSibling() ++ val arrow = element.getFunctionLiteral().getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ element.getFunctionLiteral().deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ element.getFunctionLiteral().addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ if (hasDeclaredReceiverType) { ++ val childAfterBrace = element.getFunctionLiteral().getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = paramList?.getPrevSibling() ++ element.getFunctionLiteral().deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ if (params != null && params!!.size() == 1 && params[0].getNameIdentifier() != null) { ++ paramList!!.replace(params[0].getNameIdentifier()!!) ++ } ++ else { ++ params?.forEach{","Missing a space before `{` +",2014-04-09 15:43:44 +228,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } ++ else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ val multiParameter = element.getMultiParameter() ?: return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() as? JetCallExpression ?: return false ++ ++ if (!selector.textMatches(""withIndices()"")) return false","This is a nice optimization, but I'd check if `selector` is a call expression with a callee named `withIndices`. People can have different weird code style settings, for example ones requiring spaces before parentheses; it would be a pity if this intention wouldn't work in that case (`withIndices ()`) +",2014-05-12 12:27:19 +227,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } ++ else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ val multiParameter = element.getMultiParameter() ?: return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() as? JetCallExpression ?: return false ++ ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element) ++ val callResolution = bindingContext[BindingContext.RESOLVED_CALL, selector.getCalleeExpression()!!] ?: return false ++ val fqName = DescriptorUtils.getFqNameSafe(callResolution.getCandidateDescriptor())","Ditto (`getFqNameSafe`) +",2014-05-12 12:21:26 +235,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } ++ else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ val multiParameter = element.getMultiParameter() ?: return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() as? JetCallExpression ?: return false ++ ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element) ++ val callResolution = bindingContext[BindingContext.RESOLVED_CALL, selector.getCalleeExpression()!!] ?: return false ++ val fqName = DescriptorUtils.getFqNameSafe(callResolution.getCandidateDescriptor()) ++ if (fqName.toString() != ""kotlin.withIndices"") return false ++ ++ val indexVar = multiParameter.getEntries()[0]","You should check if there are any entries. Otherwise your intention fails with the exception on the following test case: + +``` kotlin + for (() in listOf(1).withIndices()) { + } +``` +",2014-05-12 13:22:11 +234,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } ++ else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ val multiParameter = element.getMultiParameter() ?: return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() as? JetCallExpression ?: return false ++ ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element) ++ val callResolution = bindingContext[BindingContext.RESOLVED_CALL, selector.getCalleeExpression()!!] ?: return false ++ val fqName = DescriptorUtils.getFqNameSafe(callResolution.getCandidateDescriptor()) ++ if (fqName.toString() != ""kotlin.withIndices"") return false ++ ++ val indexVar = multiParameter.getEntries()[0] ++ val findManager = FindManager.getInstance(element.getProject()) as FindManagerImpl ++ val findHandler = findManager.getFindUsagesManager().getFindUsagesHandler(indexVar, false) ?: return false ++ val options = KotlinPropertyFindUsagesOptions(element.getProject()) ++ var usageCount = 0","As I mentioned earlier, this should be a boolean flag, rather than an integer variable +",2014-05-12 13:14:21 +714,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMember ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.Element ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++ ++abstract class JavacMember(element: T, ++ javac: Javac) : JavacElement(element, javac), JavaMember { ++ override val containingClass: JavaClass ++ get() = JavacClass((element.enclosingElement as TypeElement), javac) ++ ++ override val annotations: Collection ++ get() = element.annotationMirrors ++ .map { JavacAnnotation(it, javac) } ++ ++ override fun findAnnotation(fqName: FqName): JavaAnnotation? = element.annotationMirrors ++ .filter { it.toString() == fqName.asString() } ++ .firstOrNull() ++ ?.let { JavacAnnotation(it, javac) } ++ ++ override val visibility ++ get() = element.getVisibility() ++ ++ override val name ++ get() = Name.identifier(element.simpleName.toString()) ++ ++ override val isDeprecatedInJavaDoc = false","Again, why false?",2017-04-05 15:02:01 +716,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMember ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.Element ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++ ++abstract class JavacMember(element: T, ++ javac: Javac) : JavacElement(element, javac), JavaMember { ++ override val containingClass: JavaClass ++ get() = JavacClass((element.enclosingElement as TypeElement), javac) ++ ++ override val annotations: Collection ++ get() = element.annotationMirrors ++ .map { JavacAnnotation(it, javac) } ++ ++ override fun findAnnotation(fqName: FqName): JavaAnnotation? = element.annotationMirrors ++ .filter { it.toString() == fqName.asString() } ++ .firstOrNull() ++ ?.let { JavacAnnotation(it, javac) } ++ ++ override val visibility ++ get() = element.getVisibility() ++ ++ override val name ++ get() = Name.identifier(element.simpleName.toString()) ++ ++ override val isDeprecatedInJavaDoc = false ++ ++ override val isAbstract ++ get() = element.isAbstract ++ ++ override val isStatic ++ get() = element.isStatic ++ ++ override val isFinal ++ get() = element.isFinal ++ ++} ++ ++fun ExecutableElement.valueParameters(javac: Javac) = let {",May be create separate file like `JavacElementUtils.kt` for such things.,2017-04-05 15:04:24 +715,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.symbols ++ ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.load.java.structure.JavaAnnotation ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaMember ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.Name ++import javax.lang.model.element.Element ++import javax.lang.model.element.ExecutableElement ++import javax.lang.model.element.TypeElement ++ ++abstract class JavacMember(element: T, ++ javac: Javac) : JavacElement(element, javac), JavaMember { ++ override val containingClass: JavaClass ++ get() = JavacClass((element.enclosingElement as TypeElement), javac) ++ ++ override val annotations: Collection ++ get() = element.annotationMirrors ++ .map { JavacAnnotation(it, javac) } ++ ++ override fun findAnnotation(fqName: FqName): JavaAnnotation? = element.annotationMirrors ++ .filter { it.toString() == fqName.asString() } ++ .firstOrNull() ++ ?.let { JavacAnnotation(it, javac) } ++ ++ override val visibility ++ get() = element.getVisibility() ++ ++ override val name ++ get() = Name.identifier(element.simpleName.toString()) ++ ++ override val isDeprecatedInJavaDoc = false ++ ++ override val isAbstract ++ get() = element.isAbstract ++ ++ override val isStatic ++ get() = element.isStatic ++ ++ override val isFinal ++ get() = element.isFinal ++ ++} ++ ++fun ExecutableElement.valueParameters(javac: Javac) = let { ++ val parameterTypesCount = parameters.size ++ ++ parameters.mapIndexed { index, it -> ++ val isLastParameter = index == parameterTypesCount - 1 ++ val parameterName = it.simpleName.toString() ++ JavacValueParameter(it, parameterName, if (isLastParameter) isVarArgs else false, javac)",`isLastParameter && isVarArgs`,2017-04-05 15:03:47 +832,"@@ -0,0 +1,70 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.code.Flags ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.descriptors.Visibilities ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaField ++import org.jetbrains.kotlin.name.Name ++ ++class TreeBasedField(tree: T, ++ treePath: TreePath, ++ containingClass: JavaClass, ++ javac: JavacWrapper) : TreeBasedMember(tree, treePath, containingClass, javac), JavaField { ++ ++ override val name ++ get() = Name.identifier(tree.name.toString()) ++ ++ override val isAbstract ++ get() = tree.modifiers.isAbstract ++ ++ override val isStatic ++ get() = containingClass.isInterface || tree.modifiers.isStatic",Please ensure there's a test on static fields in annotations,2017-04-25 16:37:02 +569,"@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.references.mainReference ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++ ++class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ val patterns = mapOf( ++ ""java.io.PrintStream.println"" to ""println($0)"", ++ ""java.io.PrintStream.print"" to ""print($0)"", ++ ""java.util.Collections.sort"" to ""$0.sort()"" ++ ) ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitQualifiedExpression(expression: KtQualifiedExpression) { ++ super.visitQualifiedExpression(expression) ++ ++ val selectorExpression = expression.selectorExpression ?: return ++ if (selectorExpression !is KtCallExpression) return ++ val value = selectorExpression.valueArguments.singleOrNull() ?: return ++ ++ val calleeExpression = selectorExpression.calleeExpression as KtSimpleNameExpression ++ val bindingContext = calleeExpression.analyze(BodyResolveMode.PARTIAL) ++ val target = calleeExpression.mainReference.resolveToDescriptors(bindingContext).singleOrNull() ?: return ++ val pattern = target.fqNameSafe.asString()","I tryed use `importableFqName` but it's was giving null for me. I am a bit confused with this. +",2016-05-20 02:37:19 +660,"@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo ++import org.jetbrains.kotlin.idea.refactoring.getLineNumber ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtBlockExpression ++import org.jetbrains.kotlin.psi.KtLambdaExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++ ++class UnusedEqualsInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ super.visitBinaryExpression(expression) ++ if (expression.operationToken != KtTokens.EQEQ) return ++ val parent = expression.parent as? KtBlockExpression ?: return ++ val lastBlockStatement = parent.lastBlockStatementOrThis() ++ when { ++ expression.evaluatesTo(lastBlockStatement) && expression.getLineNumber() == lastBlockStatement.getLineNumber() -> ++ expression.getStrictParentOfType()?.visitLambdaExpression(holder, expression) ?: holder.registerUnusedEqualsProblem(expression)",All of this looks too nasty and unsafe. Please use `KtExpression.isUsedAsExpression` from `BindingContextUtils.kt` to determine whether your `equals` result is used or not.,2016-12-23 10:08:19 +662,"@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo ++import org.jetbrains.kotlin.idea.refactoring.getLineNumber ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtBlockExpression ++import org.jetbrains.kotlin.psi.KtLambdaExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++ ++class UnusedEqualsInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ super.visitBinaryExpression(expression) ++ if (expression.operationToken != KtTokens.EQEQ) return ++ val parent = expression.parent as? KtBlockExpression ?: return ++ val lastBlockStatement = parent.lastBlockStatementOrThis() ++ when { ++ expression.evaluatesTo(lastBlockStatement) && expression.getLineNumber() == lastBlockStatement.getLineNumber() -> ++ expression.getStrictParentOfType()?.visitLambdaExpression(holder, expression) ?: holder.registerUnusedEqualsProblem(expression) ++ else -> holder.registerUnusedEqualsProblem(expression) ++ } ++ } ++ ++ private fun KtLambdaExpression.visitLambdaExpression(holder: ProblemsHolder, expression: KtBinaryExpression) { ++ val lambdaTypeArguments = getType(analyze())?.arguments ?: return ++ if (lambdaTypeArguments.size != 1) return ++ when { ++ KotlinBuiltIns.isBoolean(lambdaTypeArguments[0].type) -> { ++ val lastBlockStatementOrThis = bodyExpression?.lastBlockStatementOrThis() ?: return ++ if (!expression.evaluatesTo(lastBlockStatementOrThis)) holder.registerUnusedEqualsProblem(expression) ++ } ++ else -> holder.registerUnusedEqualsProblem(expression) ++ } ++ } ++ ++ private fun ProblemsHolder.registerUnusedEqualsProblem(expression: KtBinaryExpression) { ++ registerProblem(expression,",I'd say it's better to provide also text range here and highlight `==` only as unused.,2016-12-23 10:13:12 +661,"@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo ++import org.jetbrains.kotlin.idea.refactoring.getLineNumber ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtBlockExpression ++import org.jetbrains.kotlin.psi.KtLambdaExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis ++import org.jetbrains.kotlin.resolve.calls.callUtil.getType ++ ++class UnusedEqualsInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ super.visitBinaryExpression(expression) ++ if (expression.operationToken != KtTokens.EQEQ) return ++ val parent = expression.parent as? KtBlockExpression ?: return ++ val lastBlockStatement = parent.lastBlockStatementOrThis() ++ when { ++ expression.evaluatesTo(lastBlockStatement) && expression.getLineNumber() == lastBlockStatement.getLineNumber() -> ++ expression.getStrictParentOfType()?.visitLambdaExpression(holder, expression) ?: holder.registerUnusedEqualsProblem(expression) ++ else -> holder.registerUnusedEqualsProblem(expression) ++ } ++ } ++ ++ private fun KtLambdaExpression.visitLambdaExpression(holder: ProblemsHolder, expression: KtBinaryExpression) { ++ val lambdaTypeArguments = getType(analyze())?.arguments ?: return ++ if (lambdaTypeArguments.size != 1) return ++ when { ++ KotlinBuiltIns.isBoolean(lambdaTypeArguments[0].type) -> { ++ val lastBlockStatementOrThis = bodyExpression?.lastBlockStatementOrThis() ?: return ++ if (!expression.evaluatesTo(lastBlockStatementOrThis)) holder.registerUnusedEqualsProblem(expression) ++ } ++ else -> holder.registerUnusedEqualsProblem(expression) ++ } ++ } ++ ++ private fun ProblemsHolder.registerUnusedEqualsProblem(expression: KtBinaryExpression) { ++ registerProblem(expression, ++ ""Unused equals expression"", ++ ProblemHighlightType.LIKE_UNUSED_SYMBOL)","Should we provide some quick fix? I'd say that in simple cases with local variables or constants binary expression could be completely deleted, but in cases like `foo() == bar()` we should get + +``` +foo() +bar() +``` + +instead",2016-12-23 10:11:29 +40,"@@ -0,0 +1,72 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.lang.ASTNode; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.impl.PsiImplUtil; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; ++import org.jetbrains.jet.lexer.JetTokens; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class RemoveSupertypeFix extends JetIntentionAction { ++ private final JetDelegationSpecifier superClass; ++ ++ public RemoveSupertypeFix(@NotNull JetDelegationSpecifier superClass) { ++ super(superClass); ++ this.superClass = superClass; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""remove.supertype"", superClass.getText()); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""remove.supertype.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ // Find the preceding comma and delete it as well. ++ // We must ignore whitespaces and comments when looking for the comma. ++ ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(superClass.getPrevSibling().getNode());","Possible NullPointerException if superClass has no previous sibling??? But will it ever have no previous sibling? +",2013-03-29 16:53:57 +10,"@@ -0,0 +1,73 @@ ++/* ++ * 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.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.impl.source.tree.LeafPsiElement; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.jet.lang.psi.JetFile; ++import org.jetbrains.jet.lexer.JetTokens; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++/** ++ * @author slukjanov aka Frostman ++ */ ++public class UnnecessaryNotNullAssertionFix implements IntentionAction {","I understand why you decided to create another class for that task but still think that there should be another logic in UnnecessaryNotNullAssertionFix and ReplaceCallFix. I propose ReplaceCallFix could also be used for replacing !!. call to something else as it can be used for introducing such calls now. And this class can could be responsible only for introducing and removing a!! postfix operation. +What do you think? +",2012-06-19 15:01:46 +12,"@@ -0,0 +1,73 @@ ++/* ++ * 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.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.impl.source.tree.LeafPsiElement; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.jet.lang.psi.JetFile; ++import org.jetbrains.jet.lexer.JetTokens; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++/** ++ * @author slukjanov aka Frostman ++ */ ++public class UnnecessaryNotNullAssertionFix implements IntentionAction { ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""remove.unnecessary.non.null.assertion""); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return getText(); ++ } ++ ++ @Override ++ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { ++ return file instanceof JetFile && getExclExclElement(editor, file) != null; ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ final PsiElement exclExcl = getExclExclElement(editor, file); ++ assert exclExcl != null; ++ ++ exclExcl.delete();","There's a problem with removing PSI element this way. It looks like IDEA can't handle the region for update correctly. I'm going to debug and fix it. It can be reproduced with this chunk of code. After applying the fix idea shows errors in internal mode (with -Didea.is.internal=true in javac string). +fun test(value : String) : String { + return value!! +} +",2012-06-26 20:27:50 +771,"@@ -0,0 +1,74 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.javac.MockKotlinClassifier ++import org.jetbrains.kotlin.load.java.structure.* ++ ++sealed class ClassifierType(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : JCType(tree, treePath, javac), JavaClassifierType { ++ ++ override val classifier by lazy { treePath.resolve(javac) } ++ ++ override val canonicalText ++ get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString() ++ ++ override val presentableText ++ get() = canonicalText ++ ++ private val typeParameter ++ get() = treePath.filter { it is JCTree.JCClassDecl || it is JCTree.JCMethodDecl } ++ .flatMap { ++ when (it) { ++ is JCTree.JCClassDecl -> it.typarams ++ is JCTree.JCMethodDecl -> it.typarams ++ else -> throw UnsupportedOperationException(""${it.kind} cannot have a type parameter"") ++ } ++ } ++ .find { it.toString().substringBefore("" "") == treePath.leaf.toString() } ++ ++} ++ ++class JCClassifierType(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : ClassifierType(tree, treePath, javac) { ++ ++ override val typeArguments: List ++ get() = emptyList() ++ ++ override val isRaw ++ get() = (classifier as? MockKotlinClassifier)?.hasTypeParameters ++ ?: (classifier as? JavaClass)?.typeParameters?.isNotEmpty() ++ ?: false ++ ++} ++ ++class JCClassifierTypeWithTypeArgument(tree: T,","May be it's not the best name. For me it's more or less obvious, that `JCClassifierTypeWithTypeArgument` is an inheritor of `JCClassifierType`, but in fact it's not so. I'd change one of these two names.",2017-04-20 10:09:15 +829,"@@ -0,0 +1,75 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.javac.MockKotlinClassifier ++import org.jetbrains.kotlin.load.java.structure.* ++ ++sealed class TreeBasedClassifierType(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedType(tree, treePath, javac), JavaClassifierType { ++ ++ override val classifier ++ get() = javac.resolve(treePath) ++ ++ override val classifierQualifiedName ++ get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString() ++ ++ override val presentableText ++ get() = classifierQualifiedName ++ ++ private val typeParameter ++ get() = treePath.filter { it is JCTree.JCClassDecl || it is JCTree.JCMethodDecl } ++ .flatMap { ++ when (it) { ++ is JCTree.JCClassDecl -> it.typarams ++ is JCTree.JCMethodDecl -> it.typarams ++ else -> throw UnsupportedOperationException(""${it.kind} cannot have a type parameter"")","You can remove `.filter { ... }` above, and use `else -> emptyList()` here",2017-04-25 16:25:29 +828,"@@ -0,0 +1,75 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.wrappers.trees ++ ++import com.sun.source.util.TreePath ++import com.sun.tools.javac.tree.JCTree ++import org.jetbrains.kotlin.javac.JavacWrapper ++import org.jetbrains.kotlin.javac.MockKotlinClassifier ++import org.jetbrains.kotlin.load.java.structure.* ++ ++sealed class TreeBasedClassifierType(tree: T, ++ treePath: TreePath, ++ javac: JavacWrapper) : TreeBasedType(tree, treePath, javac), JavaClassifierType { ++ ++ override val classifier ++ get() = javac.resolve(treePath) ++ ++ override val classifierQualifiedName ++ get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString() ++ ++ override val presentableText ++ get() = classifierQualifiedName ++ ++ private val typeParameter ++ get() = treePath.filter { it is JCTree.JCClassDecl || it is JCTree.JCMethodDecl } ++ .flatMap { ++ when (it) { ++ is JCTree.JCClassDecl -> it.typarams ++ is JCTree.JCMethodDecl -> it.typarams ++ else -> throw UnsupportedOperationException(""${it.kind} cannot have a type parameter"") ++ } ++ } ++ .find { it.toString().substringBefore("" "") == treePath.leaf.toString() } ++ ++} ++ ++class TreeBasedClassifierTypeWithoutTypeArgument(tree: T,",Consider renaming to `TreeBasedNonGenericClassifierType` and `TreeBasedGenericClassifierType`,2017-04-25 13:58:07 +98,"@@ -0,0 +1,77 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.plugin.JetBundle ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFile ++import com.intellij.psi.PsiFile ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import com.intellij.psi.PsiElement ++import com.intellij.refactoring.changeSignature.PsiCallReference ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import com.intellij.psi.PsiArrayAccessExpression ++import com.intellij.psi.impl.source.tree.java.PsiArrayAccessExpressionImpl ++import org.jetbrains.jet.lang.psi.JetVisitorVoid ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.plugin.quickfix.JetIntentionAction ++ ++public class GetCallReplacementIntention : JetSelfTargetingIntention(""get.call.replacement"", javaClass()) { ++ var project : Project? = null ++ ++ override fun invoke(project: Project, editor: Editor, file: PsiFile) { ++ this.project = project ++ super.invoke(project, editor, file) ++ } ++ ++ override fun isApplicableTo(element: JetDotQualifiedExpression): Boolean { ++ val selector : JetCallExpression? = element.getSelectorExpression() as? JetCallExpression","Code formatting is inconsistent. +",2014-01-27 21:29:48 +99,"@@ -0,0 +1,77 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.plugin.JetBundle ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFile ++import com.intellij.psi.PsiFile ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import com.intellij.psi.PsiElement ++import com.intellij.refactoring.changeSignature.PsiCallReference ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import com.intellij.psi.PsiArrayAccessExpression ++import com.intellij.psi.impl.source.tree.java.PsiArrayAccessExpressionImpl ++import org.jetbrains.jet.lang.psi.JetVisitorVoid ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.plugin.quickfix.JetIntentionAction ++ ++public class GetCallReplacementIntention : JetSelfTargetingIntention(""get.call.replacement"", javaClass()) { ++ var project : Project? = null ++ ++ override fun invoke(project: Project, editor: Editor, file: PsiFile) { ++ this.project = project ++ super.invoke(project, editor, file) ++ } ++ ++ override fun isApplicableTo(element: JetDotQualifiedExpression): Boolean { ++ val selector : JetCallExpression? = element.getSelectorExpression() as? JetCallExpression ++ val callee : JetExpression? = selector?.getCalleeExpression() ++ ++ return callee != null && callee.textMatches(""get"") ++ } ++ ++ override fun applyTo(element: JetDotQualifiedExpression, editor: Editor) { ++ val selector : JetCallExpression? = element.getSelectorExpression() as? JetCallExpression ++ val callee : JetExpression? = selector?.getCalleeExpression() ++ val arguments = selector?.getValueArgumentList() ++ assert(arguments != null) ++ val argumentsText = arguments!!.getText() ++ assert(argumentsText != null) ++ val receiver : JetExpression = element.getReceiverExpression() ++ var arrayArgumentsText = """" ++ ++ for (i in 0..argumentsText!!.length() - 1) { ++ when (i) { ++ 0 -> arrayArgumentsText += ""["" ++ argumentsText.length() - 1 -> arrayArgumentsText += ""]"" ++ else -> arrayArgumentsText += argumentsText[i] ++ } ++ } ++ ++ if (project == null) {","No need to save project to local property: it can be obtained from `element` +",2014-01-27 21:30:34 +171,"@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++import org.jetbrains.jet.lang.psi.JetCallableReferenceExpression ++ ++public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingIntention( ++ ""convert.assert.to.if.with.throw"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ if (element.getCalleeExpression()?.getText() != ""assert"") return false ++ val arguments = element.getValueArguments().size ++ val lambdas = element.getFunctionLiteralArguments().size ++ if (!(arguments == 1 && (lambdas == 1 || lambdas == 0)) && arguments != 2) return false ++ val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ val resolvedCall = context[BindingContext.RESOLVED_CALL, element.getCalleeExpression()] ++ return resolvedCall?.getResultingDescriptor()?.getContainingDeclaration()?.getName().toString() == ""kotlin"" ++ } ++ ++ override fun applyTo(element: JetCallExpression, editor: Editor) { ++ val args = element.getValueArguments() ++ val condition = args[0]?.getArgumentExpression() ++ val lambdas = element.getFunctionLiteralArguments() ++ ++ val messageExpr = if (args.size == 2) { ++ args[1]?.getArgumentExpression() ++ } else if (!lambdas.isEmpty()) { ++ element.getFunctionLiteralArguments()[0] ++ } else { ++ JetPsiFactory.createExpression(element.getProject(), ""\""Assertion failed\"""")","not sure on this line, basically i just want that string, but later i use messageExpr as an expression, so i was debating whether to create an expression with the string and then have easier handling at line 62, or i thought maybe setting messageExpr to be Any and then just assigning the string and adding a special check for String in line 62, probably more efficient but less readable. +Ended up going for readability +",2014-04-10 17:21:23 +120,"@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lexer.JetTokens ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class ReplaceWithOperatorAssignIntention : JetSelfTargetingIntention(""replace.with.operator.assign.intention"", javaClass()) { ++ override fun isApplicableTo(element: JetBinaryExpression): Boolean { ++ fun checkForNullSafety(element : JetBinaryExpression): Boolean { ++ val rightExpression = element.getRight() ++ ++ return element.getLeft() != null && ++ element.getRight() != null && ++ element.getLeft() is JetSimpleNameExpression && ++ element.getOperationToken() == JetTokens.EQ && ++ rightExpression is JetBinaryExpression && ++ rightExpression.getLeft() != null && ++ rightExpression.getRight() != null","1) Extract `element.getLeft()` just like you did for `element.getRight()` (let's call it leftExpression) +2) There is no point in using `element.getRight()`/`element.getLeft()` in comparisons since they are/will be extracted to variables +3) `leftExpression !=null` is redundant (it's implied by `leftExpression is JetSimpleNameExpression`) +The same goes for `element.getRight() != null` +4) Also I'd change the function name since it doesn't just check for null safety. Something like `isWellFormedAssignment`, for example. +",2014-02-25 14:58:08 +121,"@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lexer.JetTokens ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class ReplaceWithOperatorAssignIntention : JetSelfTargetingIntention(""replace.with.operator.assign.intention"", javaClass()) { ++ override fun isApplicableTo(element: JetBinaryExpression): Boolean { ++ fun checkForNullSafety(element : JetBinaryExpression): Boolean { ++ val rightExpression = element.getRight() ++ ++ return element.getLeft() != null && ++ element.getRight() != null && ++ element.getLeft() is JetSimpleNameExpression && ++ element.getOperationToken() == JetTokens.EQ && ++ rightExpression is JetBinaryExpression && ++ rightExpression.getLeft() != null && ++ rightExpression.getRight() != null ++ } ++ ++ fun checkExpressionRepeat(variableExpression: JetSimpleNameExpression, expression: JetBinaryExpression): Boolean { ++ if (variableExpression.getText().equals(expression.getLeft()!!.getText())) ++ return expression.getOperationToken() == JetTokens.PLUS || ++ expression.getOperationToken() == JetTokens.MINUS || ++ expression.getOperationToken() == JetTokens.MUL || ++ expression.getOperationToken() == JetTokens.DIV || ++ expression.getOperationToken() == JetTokens.PERC ++ else if (variableExpression.getText().equals(expression.getRight()!!.getText())) ++ return expression.getOperationToken() == JetTokens.PLUS || ++ expression.getOperationToken() == JetTokens.MUL ++ else if (expression.getLeft() is JetBinaryExpression) ++ return checkExpressionRepeat(variableExpression, expression.getLeft() as JetBinaryExpression) ++ else ++ return false ++ } ++","1) JetPsiMatcher class provides more reliable and generic way to compare PSI elements. Please, use it instead of comparing element text directly. For example, `JetPsiMatcher.checkElementMatch(variableExpression, expression.getLeft())` +2) I suggest to use when expression instead of nested ""ifs"". Like this: + +``` +return when { + JetPsiMatcher.checkElementMatch(variableExpression, expression.getLeft()) -> ... + ... +} +``` + +3) This function is tail-recursive, so it's worth annotating it with `tailRecursive`. Then compiler can apply tail-call optimization to it. +",2014-02-25 15:21:24 +122,"@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lexer.JetTokens ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class ReplaceWithOperatorAssignIntention : JetSelfTargetingIntention(""replace.with.operator.assign.intention"", javaClass()) { ++ override fun isApplicableTo(element: JetBinaryExpression): Boolean { ++ fun checkForNullSafety(element : JetBinaryExpression): Boolean { ++ val rightExpression = element.getRight() ++ ++ return element.getLeft() != null && ++ element.getRight() != null && ++ element.getLeft() is JetSimpleNameExpression && ++ element.getOperationToken() == JetTokens.EQ && ++ rightExpression is JetBinaryExpression && ++ rightExpression.getLeft() != null && ++ rightExpression.getRight() != null ++ } ++ ++ fun checkExpressionRepeat(variableExpression: JetSimpleNameExpression, expression: JetBinaryExpression): Boolean { ++ if (variableExpression.getText().equals(expression.getLeft()!!.getText())) ++ return expression.getOperationToken() == JetTokens.PLUS || ++ expression.getOperationToken() == JetTokens.MINUS || ++ expression.getOperationToken() == JetTokens.MUL || ++ expression.getOperationToken() == JetTokens.DIV || ++ expression.getOperationToken() == JetTokens.PERC ++ else if (variableExpression.getText().equals(expression.getRight()!!.getText())) ++ return expression.getOperationToken() == JetTokens.PLUS || ++ expression.getOperationToken() == JetTokens.MUL ++ else if (expression.getLeft() is JetBinaryExpression) ++ return checkExpressionRepeat(variableExpression, expression.getLeft() as JetBinaryExpression) ++ else ++ return false ++ } ++ ++ if (checkForNullSafety(element)) { ++ return checkExpressionRepeat(element.getLeft() as JetSimpleNameExpression, element.getRight() as JetBinaryExpression) ++ } else { ++ return false ++ } ++ } ++ ++ override fun applyTo(element: JetBinaryExpression, editor: Editor) { ++ fun buildReplacement(variableExpression: JetSimpleNameExpression, expression: JetBinaryExpression, replacementBuilder: StringBuilder): String {","This function is also tail-recursive, so please add [tailRecursive] annotation. +",2014-02-25 16:12:47 +700,"@@ -0,0 +1,79 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.descriptors.ClassDescriptor ++import org.jetbrains.kotlin.descriptors.ConstructorDescriptor ++import org.jetbrains.kotlin.descriptors.PropertyDescriptor ++import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor ++import org.jetbrains.kotlin.load.java.components.JavaResolverCache ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++import org.jetbrains.kotlin.load.java.structure.JavaField ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.tail ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.lazy.ResolveSession ++import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils ++import javax.inject.Inject ++ ++class JavacJavaResolverCache : JavaResolverCache {",Here we also could extract `AbstractJavaResolverCache`,2017-04-05 12:56:06 +699,"@@ -0,0 +1,79 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import org.jetbrains.kotlin.descriptors.ClassDescriptor ++import org.jetbrains.kotlin.descriptors.ConstructorDescriptor ++import org.jetbrains.kotlin.descriptors.PropertyDescriptor ++import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor ++import org.jetbrains.kotlin.load.java.components.JavaResolverCache ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.JavaElement ++import org.jetbrains.kotlin.load.java.structure.JavaField ++import org.jetbrains.kotlin.load.java.structure.JavaMethod ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.name.tail ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.lazy.ResolveSession ++import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils ++import javax.inject.Inject ++ ++class JavacJavaResolverCache : JavaResolverCache { ++ ++ private lateinit var trace: BindingTrace ++ private lateinit var resolveSession: ResolveSession","In `LazyJavaResolverCache` both of them are `val`, why we do not want the same behaviour here?",2017-04-05 12:54:49 +52,"@@ -0,0 +1,8 @@ ++// ""Create method 'get' from usage"" ""true"" ++import java.util.ArrayList ++ ++class Foo {","Isn't it better to remove type parameter of class to avoid confusing when reading test? Or is it intentional? +",2013-04-26 11:17:17 +34,"@@ -0,0 +1,8 @@ ++enum class E { ++FOO ++fun foo() : Unit { ++FOO.toString() ++} ++public fun name() : String { return """" } ++public fun order() : Int { return 0 } ++} +\ No newline at end of file","The same: code formatting is wrong +",2013-02-21 14:58:31 +346,"@@ -0,0 +1,8 @@ ++var status: String = ""fail""","I beleive it would be good to add comment explaining why ""status"" here is top-level property instead of local variable. +",2015-03-26 15:33:16 +172,"@@ -0,0 +1,80 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++import org.jetbrains.jet.lang.psi.JetCallableReferenceExpression ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++ ++public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingIntention( ++ ""convert.assert.to.if.with.throw"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ if (element.getCalleeExpression()?.getText() != ""assert"") return false ++ val arguments = element.getValueArguments().size ++ val lambdas = element.getFunctionLiteralArguments().size ++ if (!(arguments == 1 && (lambdas == 1 || lambdas == 0)) && arguments != 2) return false ++ val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ val resolvedCall = context[BindingContext.RESOLVED_CALL, element.getCalleeExpression()] ++ if (resolvedCall == null) return false ++ return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() == ""kotlin.assert""","fixed to use DescriptorUtils.getFqName +",2014-04-14 22:32:03 +173,"@@ -0,0 +1,80 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.plugin.codeInsight.ShortenReferences ++import org.jetbrains.jet.lang.psi.JetCallableReferenceExpression ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++ ++public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingIntention( ++ ""convert.assert.to.if.with.throw"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ if (element.getCalleeExpression()?.getText() != ""assert"") return false ++ val arguments = element.getValueArguments().size ++ val lambdas = element.getFunctionLiteralArguments().size ++ if (!(arguments == 1 && (lambdas == 1 || lambdas == 0)) && arguments != 2) return false ++ val context = AnalyzerFacadeWithCache.getContextForElement(element) ++ val resolvedCall = context[BindingContext.RESOLVED_CALL, element.getCalleeExpression()] ++ if (resolvedCall == null) return false ++ return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() == ""kotlin.assert"" ++ } ++ ++ override fun applyTo(element: JetCallExpression, editor: Editor) { ++ val args = element.getValueArguments() ++ val condition = args[0]?.getArgumentExpression() ++ val lambdas = element.getFunctionLiteralArguments() ++ ++ val messageExpr = if (args.size == 2) { ++ args[1]?.getArgumentExpression() ++ } else if (lambdas.isNotEmpty()) {","!lambdas.isEmpty changed to lambdas.isNotEmpty() +",2014-04-14 22:32:53 +183,"@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) {","Ditto (`paramsTextRange != null && caretLocation in paramsTextRange` or `paramsTextRange?.contains(caretLocation) ?: false`) +",2014-04-16 18:26:38 +182,"@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) { ++ caretLocation in paramsTextRange ++ } ++ else false ++ if (!(caretLocation == openBraceOffset + 1 || caretLocation == closeBraceOffset || caretIsInParams)) return false","Ditto +",2014-04-16 18:25:53 +184,"@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val paramsTextRange = element.getFunctionLiteral().getValueParameterList()?.getTextRange() ++ val caretIsInParams = if (paramsTextRange != null) { ++ caretLocation in paramsTextRange ++ } ++ else false ++ if (!(caretLocation == openBraceOffset + 1 || caretLocation == closeBraceOffset || caretIsInParams)) return false ++ ++ val params = element.getValueParameters() ++ val hasDeclaredParamsType = params.any { it.getTypeReference() != null } ++ val hasDeclaredReturnType = element.hasDeclaredReturnType() ++ val hasDeclaredReceiverType = element.getFunctionLiteral().getReceiverTypeRef() != null ++ if (hasDeclaredParamsType || hasDeclaredReturnType || hasDeclaredReceiverType) return true","I think I noticed the first time: such code creates a false sense that the applicability of the intention here depends on all three of these variables. Your code should look more like this: +1. if has declared params type, return true +2. if has declared return type, return true +3. if has declared receiver type, return true +4. return false + +Once you refactor your code to look like this, you'll notice that these variables are no longer needed since they can be inlined. This will make the code shorter. Please do this. +",2014-04-16 18:29:37 +566,"@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.KtNodeTypes ++import org.jetbrains.kotlin.psi.* ++ ++class RedundantIfInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitIfExpression(expression: KtIfExpression) { ++ super.visitIfExpression(expression) ++ ++ if (expression.condition != null && isRedundant(expression)) { ++ holder.registerProblem(expression, ++ ""Redundant 'if' statement"", ++ ProblemHighlightType.LIKE_UNUSED_SYMBOL, ++ RemoveRedundantIf) ++ } ++ } ++ } ++ } ++ ++ private fun isRedundant(expression: KtIfExpression): Boolean { ++ val thenReturn = getReturnedExpression(expression.then) ?: return false ++ val elseReturn = getReturnedExpression(expression.`else`) ?: return false ++ ++ if (KtPsiUtil.isTrueConstant(thenReturn) && !KtPsiUtil.isTrueConstant(elseReturn)) {","I find it somewhat confusing that the KtNodeTypes.BOOLEAN_CONSTANT check is separate from the value check. It would be clearer to add the corresponding `isFalseConstant()` method to `KtPsiUtil` and to remove the node type check from `getReturnedExpression()`. +",2016-05-18 13:37:45 +564,"@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.KtNodeTypes ++import org.jetbrains.kotlin.psi.* ++ ++class RedundantIfInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitIfExpression(expression: KtIfExpression) { ++ super.visitIfExpression(expression) ++ ++ if (expression.condition != null && isRedundant(expression)) { ++ holder.registerProblem(expression, ++ ""Redundant 'if' statement"", ++ ProblemHighlightType.LIKE_UNUSED_SYMBOL, ++ RemoveRedundantIf) ++ } ++ } ++ } ++ } ++ ++ private fun isRedundant(expression: KtIfExpression): Boolean { ++ val thenReturn = getReturnedExpression(expression.then) ?: return false ++ val elseReturn = getReturnedExpression(expression.`else`) ?: return false ++ ++ if (KtPsiUtil.isTrueConstant(thenReturn) && !KtPsiUtil.isTrueConstant(elseReturn)) { ++ return true ++ } ++ ++ if (!KtPsiUtil.isTrueConstant(thenReturn) && KtPsiUtil.isTrueConstant(elseReturn)) { ++ return true ++ } ++ ++ return false ++ } ++ ++ private fun getReturnedExpression(expression: KtExpression?) : KtExpression? { ++ if (expression == null) return null ++ if (expression !is KtBlockExpression) return null","This check isn't necessary: a statement where `return` is not enclosed in braces is no less trivial. +",2016-05-18 13:31:51 +565,"@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.KtNodeTypes ++import org.jetbrains.kotlin.psi.* ++ ++class RedundantIfInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitIfExpression(expression: KtIfExpression) { ++ super.visitIfExpression(expression) ++ ++ if (expression.condition != null && isRedundant(expression)) { ++ holder.registerProblem(expression, ++ ""Redundant 'if' statement"", ++ ProblemHighlightType.LIKE_UNUSED_SYMBOL, ++ RemoveRedundantIf) ++ } ++ } ++ } ++ } ++ ++ private fun isRedundant(expression: KtIfExpression): Boolean { ++ val thenReturn = getReturnedExpression(expression.then) ?: return false ++ val elseReturn = getReturnedExpression(expression.`else`) ?: return false ++ ++ if (KtPsiUtil.isTrueConstant(thenReturn) && !KtPsiUtil.isTrueConstant(elseReturn)) { ++ return true ++ } ++ ++ if (!KtPsiUtil.isTrueConstant(thenReturn) && KtPsiUtil.isTrueConstant(elseReturn)) { ++ return true ++ } ++ ++ return false ++ } ++ ++ private fun getReturnedExpression(expression: KtExpression?) : KtExpression? { ++ if (expression == null) return null ++ if (expression !is KtBlockExpression) return null ++ if (expression.statements.size != 1) return null ++ ++ val statement = expression.statements[0]","`expression.statements.singleOrNull() as? KtReturnExpression ?: return null` +",2016-05-18 13:32:40 +536,"@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers ++import org.jetbrains.kotlin.idea.util.ShortenReferences ++import org.jetbrains.kotlin.psi.KtClassOrObject ++import org.jetbrains.kotlin.psi.KtExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.isInterface ++import org.jetbrains.kotlin.types.typeUtil.supertypes ++ ++private fun KotlinType.renderShort() = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(this) ++ ++private fun KotlinType.getSuperTypesRecursive() = constructor.supertypes.let { it + it.flatMap { it.supertypes() } }","BTW, this is exponential; please use `TypeUtils#getAllSupertypes` instead +",2016-04-01 14:19:36 +574,"@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.references.mainReference ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++ ++class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ private val patterns = mapOf( ++ ""java.io.PrintStream.println"" to Pair(""println($0)"", ConversionType.METHOD),","What about other usages of `PrintStream.println` outside of `System.out`, e.g. `System.err`? This will produce a lot of false positives. +",2016-05-24 14:21:19 +595,"@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.references.mainReference ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++ ++class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ private val patterns = mapOf( ++ ""java.io.PrintStream.println"" to Pair(""println($0)"", ConversionType.METHOD), ++ ""java.io.PrintStream.print"" to Pair(""print($0)"", ConversionType.METHOD), ++ ""java.util.Collections.sort"" to Pair(""$0.sort()"", ConversionType.METHOD), ++ ""java.util.HashMap.put"" to Pair(""$0[$1] = $2"", ConversionType.ASSIGNMENT)","Why limit to `HashMap`? +",2016-08-25 12:50:11 +596,"@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.references.mainReference ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++ ++class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ ++ private val patterns = mapOf( ++ ""java.io.PrintStream.println"" to Pair(""println($0)"", ConversionType.METHOD), ++ ""java.io.PrintStream.print"" to Pair(""print($0)"", ConversionType.METHOD), ++ ""java.util.Collections.sort"" to Pair(""$0.sort()"", ConversionType.METHOD), ++ ""java.util.HashMap.put"" to Pair(""$0[$1] = $2"", ConversionType.ASSIGNMENT) ++ ) ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitQualifiedExpression(expression: KtQualifiedExpression) { ++ super.visitQualifiedExpression(expression) ++ ++ val selectorExpression = expression.selectorExpression ++ if(selectorExpression !is KtCallExpression) return ++ val args = selectorExpression.valueArguments ++ if(args.isEmpty()) return ++ ++ val calleeExpression = selectorExpression.calleeExpression as? KtSimpleNameExpression ?: return ++ val bindingContext = calleeExpression.analyze(BodyResolveMode.PARTIAL) ++ val target = calleeExpression.mainReference.resolveToDescriptors(bindingContext).singleOrNull() ?: return","You can use `findOriginalTopMostOverriddenDescriptors` e.g. to to get `MutableMap.put` instead of `HashMap.put` +",2016-08-25 12:51:28 +531,"@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.descriptors.ClassDescriptor ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf ++ ++private val JAVA_LANG_CLASS_FQ_NAME = FqName(""java.lang.Class"") ++ ++private fun KotlinType.isJClass(): Boolean { ++ val expressionTypeFqName = constructor.declarationDescriptor?.fqNameSafe ?: return false ++ return expressionTypeFqName == JAVA_LANG_CLASS_FQ_NAME ++} ++ ++class ConvertClassToKClassFix(element: KtDotQualifiedExpression, private val type: KotlinType) : KotlinQuickFixAction(element) { ++ override fun getText() = ""Remove '.${element.children.lastOrNull()?.text}'"" ++ override fun getFamilyName() = ""Remove conversion from 'KClass' to 'Class'"" ++ ++ ++ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { ++ if (!super.isAvailable(project, editor, file)) return false ++ ++ val expressionType = element.analyze(BodyResolveMode.PARTIAL).getType(element) ?: return false ++ if (!expressionType.isJClass()) return false ++ ++ val children = element.children ++ if (children.size != 2) return false ++ ++ val firstChild = children.first() as? KtExpression ?: return false ++ val firstChildType = firstChild.analyze(BodyResolveMode.PARTIAL).getType(firstChild) ?: return false","You should reuse the BindingContext from the first analyze() call. +",2016-03-23 14:12:43 +532,"@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.codeInsight.intention.IntentionAction ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.descriptors.ClassDescriptor ++import org.jetbrains.kotlin.diagnostics.Diagnostic ++import org.jetbrains.kotlin.diagnostics.Errors ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.psi.KtDotQualifiedExpression ++import org.jetbrains.kotlin.psi.KtExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++import org.jetbrains.kotlin.types.KotlinType ++import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf ++ ++private val JAVA_LANG_CLASS_FQ_NAME = FqName(""java.lang.Class"") ++ ++private fun KotlinType.isJClass(): Boolean { ++ val expressionTypeFqName = constructor.declarationDescriptor?.fqNameSafe ?: return false ++ return expressionTypeFqName == JAVA_LANG_CLASS_FQ_NAME ++} ++ ++class ConvertClassToKClassFix(element: KtDotQualifiedExpression, private val type: KotlinType) : KotlinQuickFixAction(element) { ++ override fun getText() = ""Remove '.${element.children.lastOrNull()?.text}'"" ++ override fun getFamilyName() = ""Remove conversion from 'KClass' to 'Class'"" ++ ++ ++ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { ++ if (!super.isAvailable(project, editor, file)) return false ++ ++ val expressionType = element.analyze(BodyResolveMode.PARTIAL).getType(element) ?: return false ++ if (!expressionType.isJClass()) return false ++ ++ val children = element.children ++ if (children.size != 2) return false ++ ++ val firstChild = children.first() as? KtExpression ?: return false ++ val firstChildType = firstChild.analyze(BodyResolveMode.PARTIAL).getType(firstChild) ?: return false ++ ++ return firstChildType.isSubtypeOf(type) ++ } ++ ++ override fun invoke(project: Project, editor: Editor?, file: KtFile) { ++ val lastChild = element.children.lastOrNull() ?: return ++ editor?.document?.replaceString(lastChild.startOffset - 1, lastChild.endOffset, """")","The quickfix will do nothing if there is no editor. It's possible to perform the change through the PSI, and it's better to do it that way. +",2016-03-23 14:13:21 +697,"@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.components ++ ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.vfs.VirtualFile ++import com.intellij.psi.search.DelegatingGlobalSearchScope ++import com.intellij.psi.search.GlobalSearchScope ++import org.jetbrains.kotlin.javac.Javac ++import org.jetbrains.kotlin.idea.KotlinFileType ++import org.jetbrains.kotlin.load.java.JavaClassFinder ++import org.jetbrains.kotlin.name.ClassId ++import org.jetbrains.kotlin.name.FqName ++import org.jetbrains.kotlin.resolve.BindingTrace ++import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer ++import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer ++import javax.annotation.PostConstruct ++import javax.inject.Inject ++ ++class JavacClassFinder : JavaClassFinder {",JavacBasedClassFinder?,2017-04-05 12:27:33 +229,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import com.intellij.psi.util.PsiTreeUtil ++import com.intellij.psi.PsiDocumentManager ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import com.intellij.codeInsight.template.TemplateBuilderImpl ++import com.intellij.codeInsight.template.impl.TemplateManagerImpl ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++import org.jetbrains.jet.analyzer.analyzeInContext ++import org.jetbrains.jet.lang.psi.JetCallExpression ++ ++public class AddForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""add.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val loopRange = element.getLoopRange()!! ++ val newRangeText = ""${loopRange.getText()}.withIndices()"" ++ val newRange = JetPsiFactory.createExpression(editor.getProject(), newRangeText) ++ ++ //Roundabout way to create new multiparameter element so as not to incorrectly trigger syntax error highlighting ++ val loopParameter = element.getLoopParameter()!! ++ val parenthesizedParam = JetPsiFactory.createExpression(editor.getProject(), ""(index)"") as JetParenthesizedExpression ++ val indexElement = parenthesizedParam.getExpression()!! ++ val comma = JetPsiFactory.createComma(editor.getProject()) ++ val newParamElement = JetPsiFactory.createExpression(editor.getProject(), "" ${loopParameter.getText()}"") ++ parenthesizedParam.addAfter(newParamElement, indexElement) ++ parenthesizedParam.addAfter(comma, indexElement) ++ ++ loopParameter.replace(parenthesizedParam) ++ loopRange.replace(newRange) ++ ++ val multiParameter = PsiTreeUtil.findChildOfType(element, indexElement.javaClass)!! ++ ++ editor.getCaretModel().moveToOffset(multiParameter.getTextOffset()) ++ val templateBuilder = TemplateBuilderImpl(multiParameter) ++ templateBuilder.replaceElement(multiParameter, ""index"") ++ val manager = TemplateManagerImpl(editor.getProject()) ++ PsiDocumentManager.getInstance(editor.getProject()!!).doPostponedOperationsAndUnblockDocument(editor.getDocument()) ++ manager.startTemplate(editor, templateBuilder.buildInlineTemplate()!!) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getLoopParameter() == null) return false ++ val range = element.getLoopRange() ?: return false ++ if (range is JetDotQualifiedExpression) { ++ val selector = range.getSelectorExpression() ?: return true ++ if (selector.getText() == ""withIndices()"") return false","The same here, I wouldn't want **add withIndices** intention to be applicable where I've typed `withIndices ()` +",2014-05-12 12:28:28 +226,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import com.intellij.psi.util.PsiTreeUtil ++import com.intellij.psi.PsiDocumentManager ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import com.intellij.codeInsight.template.TemplateBuilderImpl ++import com.intellij.codeInsight.template.impl.TemplateManagerImpl ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++import org.jetbrains.jet.analyzer.analyzeInContext ++import org.jetbrains.jet.lang.psi.JetCallExpression ++ ++public class AddForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""add.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val loopRange = element.getLoopRange()!! ++ val newRangeText = ""${loopRange.getText()}.withIndices()"" ++ val newRange = JetPsiFactory.createExpression(editor.getProject(), newRangeText) ++ ++ //Roundabout way to create new multiparameter element so as not to incorrectly trigger syntax error highlighting ++ val loopParameter = element.getLoopParameter()!! ++ val parenthesizedParam = JetPsiFactory.createExpression(editor.getProject(), ""(index)"") as JetParenthesizedExpression ++ val indexElement = parenthesizedParam.getExpression()!! ++ val comma = JetPsiFactory.createComma(editor.getProject()) ++ val newParamElement = JetPsiFactory.createExpression(editor.getProject(), "" ${loopParameter.getText()}"") ++ parenthesizedParam.addAfter(newParamElement, indexElement) ++ parenthesizedParam.addAfter(comma, indexElement) ++ ++ loopParameter.replace(parenthesizedParam) ++ loopRange.replace(newRange) ++ ++ val multiParameter = PsiTreeUtil.findChildOfType(element, indexElement.javaClass)!! ++ ++ editor.getCaretModel().moveToOffset(multiParameter.getTextOffset()) ++ val templateBuilder = TemplateBuilderImpl(multiParameter) ++ templateBuilder.replaceElement(multiParameter, ""index"") ++ val manager = TemplateManagerImpl(editor.getProject()) ++ PsiDocumentManager.getInstance(editor.getProject()!!).doPostponedOperationsAndUnblockDocument(editor.getDocument()) ++ manager.startTemplate(editor, templateBuilder.buildInlineTemplate()!!) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getLoopParameter() == null) return false ++ val range = element.getLoopRange() ?: return false ++ if (range is JetDotQualifiedExpression) { ++ val selector = range.getSelectorExpression() ?: return true ++ if (selector.getText() == ""withIndices()"") return false ++ } ++ ++ val potentialExpression = JetPsiFactory.createExpression(element.getProject(), ++ ""${range.getText()}.withIndices()"") as JetDotQualifiedExpression ++ ++ val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element) ++ val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, element] ?: return false ++ val functionSelector = potentialExpression.getSelectorExpression() as JetCallExpression ++ val updatedContext = potentialExpression.analyzeInContext(scope) ++ val callScope = updatedContext[BindingContext.RESOLVED_CALL, functionSelector.getCalleeExpression()!!] ?: return false ++ val callFqName = DescriptorUtils.getFqNameSafe(callScope.getCandidateDescriptor())","You shouldn't call `getFqNameSafe`, because FQ name can be unsafe here (consider functions in class objects) +",2014-05-12 12:21:10 +217,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState ++import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider ++import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor ++import com.intellij.debugger.jdi.LocalVariablesUtil ++import com.siyeh.ig.psiutils.VariableAccessUtils ++import com.google.dart.compiler.util.AstUtil ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getMultiParameter() == null) return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() ?: return false ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val indexVar = element.getMultiParameter()!!.getEntries()[0] ++ ++ val findManager = FindManager.getInstance(element.getProject()) as FindManagerImpl ++ val findHandler = findManager.getFindUsagesManager().getFindUsagesHandler(indexVar,false) ?: return false ++ val options = KotlinPropertyFindUsagesOptions(element.getProject()) ++ val usageCount = array(0)","Once again experience the power of Kotlin and just use a `var` here +",2014-04-30 18:58:37 +219,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState ++import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider ++import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor ++import com.intellij.debugger.jdi.LocalVariablesUtil ++import com.siyeh.ig.psiutils.VariableAccessUtils ++import com.google.dart.compiler.util.AstUtil ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getMultiParameter() == null) return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() ?: return false ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val indexVar = element.getMultiParameter()!!.getEntries()[0] ++ ++ val findManager = FindManager.getInstance(element.getProject()) as FindManagerImpl ++ val findHandler = findManager.getFindUsagesManager().getFindUsagesHandler(indexVar,false) ?: return false ++ val options = KotlinPropertyFindUsagesOptions(element.getProject()) ++ val usageCount = array(0) ++ val usageFinderRunnable = object : Runnable { ++ override fun run() { ++ val processor = object : Processor { ++ override fun process(t: UsageInfo?): Boolean { ++ usageCount[0] = usageCount[0] + 1","How about `++`? +",2014-04-30 19:13:00 +220,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState ++import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider ++import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor ++import com.intellij.debugger.jdi.LocalVariablesUtil ++import com.siyeh.ig.psiutils.VariableAccessUtils ++import com.google.dart.compiler.util.AstUtil ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getMultiParameter() == null) return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() ?: return false ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val indexVar = element.getMultiParameter()!!.getEntries()[0] ++ ++ val findManager = FindManager.getInstance(element.getProject()) as FindManagerImpl ++ val findHandler = findManager.getFindUsagesManager().getFindUsagesHandler(indexVar,false) ?: return false ++ val options = KotlinPropertyFindUsagesOptions(element.getProject()) ++ val usageCount = array(0) ++ val usageFinderRunnable = object : Runnable { ++ override fun run() { ++ val processor = object : Processor { ++ override fun process(t: UsageInfo?): Boolean { ++ usageCount[0] = usageCount[0] + 1 ++ return true","Do you really need to continue processing all usages if you've already found one? This also means that you should just have a boolean flag instead of an integer value +",2014-04-30 19:13:56 +221,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState ++import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider ++import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor ++import com.intellij.debugger.jdi.LocalVariablesUtil ++import com.siyeh.ig.psiutils.VariableAccessUtils ++import com.google.dart.compiler.util.AstUtil ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getMultiParameter() == null) return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() ?: return false ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val indexVar = element.getMultiParameter()!!.getEntries()[0] ++ ++ val findManager = FindManager.getInstance(element.getProject()) as FindManagerImpl ++ val findHandler = findManager.getFindUsagesManager().getFindUsagesHandler(indexVar,false) ?: return false ++ val options = KotlinPropertyFindUsagesOptions(element.getProject()) ++ val usageCount = array(0) ++ val usageFinderRunnable = object : Runnable { ++ override fun run() { ++ val processor = object : Processor { ++ override fun process(t: UsageInfo?): Boolean { ++ usageCount[0] = usageCount[0] + 1 ++ return true ++ } ++ } ++ findHandler.processElementUsages(indexVar,processor,options)","`Processor` is a Java interface with a single method (SAM interface), so you should be able to just pass a lambda instead of an object expression, thanks to SAM conversion in Kotlin +",2014-04-30 19:16:23 +222,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState ++import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider ++import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor ++import com.intellij.debugger.jdi.LocalVariablesUtil ++import com.siyeh.ig.psiutils.VariableAccessUtils ++import com.google.dart.compiler.util.AstUtil ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getMultiParameter() == null) return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() ?: return false ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val indexVar = element.getMultiParameter()!!.getEntries()[0] ++ ++ val findManager = FindManager.getInstance(element.getProject()) as FindManagerImpl ++ val findHandler = findManager.getFindUsagesManager().getFindUsagesHandler(indexVar,false) ?: return false ++ val options = KotlinPropertyFindUsagesOptions(element.getProject()) ++ val usageCount = array(0) ++ val usageFinderRunnable = object : Runnable { ++ override fun run() { ++ val processor = object : Processor { ++ override fun process(t: UsageInfo?): Boolean { ++ usageCount[0] = usageCount[0] + 1 ++ return true ++ } ++ } ++ findHandler.processElementUsages(indexVar,processor,options) ++ } ++ } ++ usageFinderRunnable.run()","I'm not sure what's the point in creating a `Runnable` and immediately running it? +",2014-04-30 19:17:19 +218,"@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState ++import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeUtil ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.lang.psi.JetFile ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider ++import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor ++import com.intellij.debugger.jdi.LocalVariablesUtil ++import com.siyeh.ig.psiutils.VariableAccessUtils ++import com.google.dart.compiler.util.AstUtil ++import com.intellij.find.FindManager ++import com.intellij.find.impl.FindManagerImpl ++import com.intellij.usageView.UsageInfo ++import com.intellij.util.Processor ++import org.jetbrains.jet.plugin.findUsages.KotlinPropertyFindUsagesOptions ++ ++public class RemoveForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""remove.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val parameter = element.getMultiParameter()!! ++ val range = element.getLoopRange() as JetDotQualifiedExpression ++ val parameters = parameter.getEntries() ++ if (parameters.size() == 2) { ++ parameter.replace(parameters[1]) ++ } else { ++ JetPsiUtil.deleteElementWithDelimiters(parameters[0]) ++ } ++ ++ range.replace(range.getReceiverExpression()) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getMultiParameter() == null) return false ++ val range = element.getLoopRange() as? JetDotQualifiedExpression ?: return false ++ val selector = range.getSelectorExpression() ?: return false ++ if (!selector.textMatches(""withIndices()"")) return false ++ ++ val indexVar = element.getMultiParameter()!!.getEntries()[0] ++ ++ val findManager = FindManager.getInstance(element.getProject()) as FindManagerImpl ++ val findHandler = findManager.getFindUsagesManager().getFindUsagesHandler(indexVar,false) ?: return false ++ val options = KotlinPropertyFindUsagesOptions(element.getProject()) ++ val usageCount = array(0) ++ val usageFinderRunnable = object : Runnable { ++ override fun run() { ++ val processor = object : Processor { ++ override fun process(t: UsageInfo?): Boolean { ++ usageCount[0] = usageCount[0] + 1 ++ return true ++ } ++ } ++ findHandler.processElementUsages(indexVar,processor,options) ++ } ++ } ++ usageFinderRunnable.run() ++ return usageCount[0] == 0","Similarly to the first intention, I think we should check here if `withIndices` is actually resolved to `kotlin.withIndices` (don't forget about a test) +",2014-04-30 19:08:27 +47,"@@ -0,0 +1,84 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.fileEditor.FileEditorManager; ++import com.intellij.openapi.project.Project; ++import com.intellij.openapi.vfs.VirtualFile; ++import com.intellij.psi.PsiElement; ++import com.intellij.psi.PsiFile; ++import com.intellij.psi.PsiReference; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.psi.*; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class CreateClassObjectFromUsageFix extends CreateFromUsageFixBase { ++ private final JetClass klass; ++ ++ public CreateClassObjectFromUsageFix(@NotNull PsiElement element, @NotNull JetClass klass) { ++ super(element); ++ this.klass = klass; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""create.class.object.from.usage""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ PsiFile containingFile = klass.getContainingFile(); ++ VirtualFile virtualFile = containingFile.getVirtualFile(); ++ assert virtualFile != null; ++ FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); ++ fileEditorManager.openFile(virtualFile, true);","This piece of code can be replaced with `NavigationUtil.activateFileWithPsiElement(klass)` +",2013-04-26 11:07:40 +102,"@@ -0,0 +1,84 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++ ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import com.intellij.psi.PsiElement ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.ValueArgument ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class GetToSquareBracketsIntention : JetSelfTargetingIntention(""get.to.square.brackets"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ val expression = element.getCalleeExpression() as? JetSimpleNameExpression ++ ++ if (expression?.getReferencedName() != ""get"") ++ return false ++ ++ if (element.getValueArguments().isEmpty()) ++ return false ++ ++ val arguments = element.getValueArguments()","You declare this variable here, but for some reason only use it once: in other places, you still call `element.getValueArguments()` +",2014-02-06 14:41:09 +104,"@@ -0,0 +1,84 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++ ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import com.intellij.psi.PsiElement ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.ValueArgument ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class GetToSquareBracketsIntention : JetSelfTargetingIntention(""get.to.square.brackets"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ val expression = element.getCalleeExpression() as? JetSimpleNameExpression ++ ++ if (expression?.getReferencedName() != ""get"") ++ return false ++ ++ if (element.getValueArguments().isEmpty()) ++ return false ++ ++ val arguments = element.getValueArguments() ++ ++ for (argument in arguments) { ++ if (argument?.getArgumentExpression().equals(null))","Note that in Kotlin `==` is equivalent to `equals`. The former looks a lot more readable, so we usually prefer it over `equals` +",2014-02-06 14:45:44 +103,"@@ -0,0 +1,84 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++ ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import com.intellij.psi.PsiElement ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.ValueArgument ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class GetToSquareBracketsIntention : JetSelfTargetingIntention(""get.to.square.brackets"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ val expression = element.getCalleeExpression() as? JetSimpleNameExpression ++ ++ if (expression?.getReferencedName() != ""get"") ++ return false ++ ++ if (element.getValueArguments().isEmpty()) ++ return false ++ ++ val arguments = element.getValueArguments() ++ ++ for (argument in arguments) { ++ if (argument?.getArgumentExpression().equals(null)) ++ return false ++ } ++ ++ if (element.getValueArguments().any() { it!!.isNamed() })","Please don't just copy-paste code without adapting it :) Here you use `any`, but a few lines earlier you use a hand-written for-loop. You should attempt to use similar constructs for similar intents: either `any` everywhere, or for-loops everywhere. You can also combine these two and save a few lines +",2014-02-06 14:44:19 +105,"@@ -0,0 +1,84 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++ ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import com.intellij.psi.PsiElement ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.ValueArgument ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class GetToSquareBracketsIntention : JetSelfTargetingIntention(""get.to.square.brackets"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ val expression = element.getCalleeExpression() as? JetSimpleNameExpression ++ ++ if (expression?.getReferencedName() != ""get"") ++ return false ++ ++ if (element.getValueArguments().isEmpty()) ++ return false ++ ++ val arguments = element.getValueArguments() ++ ++ for (argument in arguments) { ++ if (argument?.getArgumentExpression().equals(null)) ++ return false ++ } ++ ++ if (element.getValueArguments().any() { it!!.isNamed() }) ++ return false ++ ++ return element.getTypeArguments().isEmpty() && element.getFunctionLiteralArguments().isEmpty() ++ ++ } ++ ++ override fun applyTo(element: JetCallExpression, editor: Editor) { ++ val parentElement = element.getParent() ++ val parentExpression: String? ++ ++ if (parentElement is JetDotQualifiedExpression) { ++ parentExpression = parentElement.getReceiverExpression().getText() ++ } else { ++ return","`return` in `applyTo` should give you a hint that's something's not right: your `isApplicableTo` should've already filtered out inapplicable usages and `applyTo` should only _apply_ the intention on a good code. Here it appears that your intention says that it **is applicable** to expressions other than `JetDotQualifiedExpression` (in `isApplicable`), but `applyTo` doesn't do anything on them. As a result, your intention is available on `get(0)` (without any receiver expression), but does nothing, which is not right for an intention +",2014-02-06 14:52:24 +106,"@@ -0,0 +1,84 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++ ++import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++import com.intellij.psi.PsiElement ++import org.jetbrains.jet.lang.psi.JetArrayAccessExpression ++import org.jetbrains.jet.lang.psi.ValueArgument ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetSimpleNameExpression ++ ++public class GetToSquareBracketsIntention : JetSelfTargetingIntention(""get.to.square.brackets"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetCallExpression): Boolean { ++ val expression = element.getCalleeExpression() as? JetSimpleNameExpression ++ ++ if (expression?.getReferencedName() != ""get"") ++ return false ++ ++ if (element.getValueArguments().isEmpty()) ++ return false ++ ++ val arguments = element.getValueArguments() ++ ++ for (argument in arguments) { ++ if (argument?.getArgumentExpression().equals(null)) ++ return false ++ } ++ ++ if (element.getValueArguments().any() { it!!.isNamed() }) ++ return false ++ ++ return element.getTypeArguments().isEmpty() && element.getFunctionLiteralArguments().isEmpty() ++ ++ } ++ ++ override fun applyTo(element: JetCallExpression, editor: Editor) { ++ val parentElement = element.getParent() ++ val parentExpression: String? ++ ++ if (parentElement is JetDotQualifiedExpression) { ++ parentExpression = parentElement.getReceiverExpression().getText() ++ } else { ++ return ++ } ++ var expressionString = StringBuilder() ++ expressionString.append(parentExpression) ++ expressionString.append(""["") ++ val arguments = element.getValueArguments() ++ val numberOfArguments = arguments.size()","This variable is no longer used. Please watch out for compilation warnings in your code (yellow spots on the scroll bar in IDEA) +",2014-02-06 14:53:32 +139,"@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lexer.JetTokens ++import com.intellij.psi.impl.source.tree.PsiErrorElementImpl ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++ ++ ++public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingIntention( ++ ""convert.negated.boolean.sequence"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetBinaryExpression): Boolean { ++ if (element.getParent() is JetBinaryExpression) return false // operate only on the longest sequence ++ var binaryExpression = element : JetBinaryExpression?","Maybe 'var binaryExpression : JetBinaryExpression? = element' would be best +",2014-03-17 16:21:22 +140,"@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lexer.JetTokens ++import com.intellij.psi.impl.source.tree.PsiErrorElementImpl ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++ ++ ++public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingIntention( ++ ""convert.negated.boolean.sequence"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetBinaryExpression): Boolean { ++ if (element.getParent() is JetBinaryExpression) return false // operate only on the longest sequence ++ var binaryExpression = element : JetBinaryExpression? ++ val originalOperator = element.getOperationToken() ++","What about Demorgan transformation here? +",2014-03-17 16:23:19 +141,"@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetPrefixExpression ++import org.jetbrains.jet.lexer.JetTokens ++import com.intellij.psi.impl.source.tree.PsiErrorElementImpl ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import org.jetbrains.jet.lang.psi.JetPsiUtil ++ ++ ++public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingIntention( ++ ""convert.negated.boolean.sequence"", javaClass()) { ++ ++ override fun isApplicableTo(element: JetBinaryExpression): Boolean { ++ if (element.getParent() is JetBinaryExpression) return false // operate only on the longest sequence ++ var binaryExpression = element : JetBinaryExpression? ++ val originalOperator = element.getOperationToken() ++ ++ if (!(originalOperator == (JetTokens.ANDAND)) && !(originalOperator == (JetTokens.OROR))) { ++ return false ++ } ++ ++ do { ++ val leftChild = binaryExpression?.getFirstChild() ++ val rightChild = binaryExpression?.getLastChild() ++ val operator = binaryExpression?.getOperationToken() ++ when { ++ rightChild !is JetPrefixExpression, ++ rightChild is PsiErrorElementImpl,","Why you need 'rightChild is PsiErrorElementImpl' check? +",2014-03-17 16:36:45 +943,"@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RemoveRedundantBackticksInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) {","This still handles only a random subset of PSI elements. The correct way to handle this is to override `visitKtElement` and to look for all children with element type `KtTokens.IDENTIFIER`, similar to how it's done [here](https://github.com/JetBrains/intellij-community/blob/b6dcce52194f52c921c414b7ccc01dbb3363cc7d/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java#L230)",2017-08-03 10:58:38 +947,"@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RemoveRedundantBackticksInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ val nameIdentifier = property.nameIdentifier ?: return ++ if (isRedundantBackticks(nameIdentifier)) { ++ registerProblem(holder, nameIdentifier) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ function.valueParameters.map { ++ val nameIdentifier = it.nameIdentifier ?: return@map ++ if (isRedundantBackticks(nameIdentifier)) { ++ registerProblem(holder, nameIdentifier) ++ } ++ } ++ } ++ ++ override fun visitReferenceExpression(expression: KtReferenceExpression) { ++ super.visitReferenceExpression(expression) ++ val bindingContext = expression.analyze() ++ expression.getResolvedCall(bindingContext) ?: return ++ if (isRedundantBackticks(expression)) { ++ registerProblem(holder, expression) ++ } ++ } ++ } ++ } ++ ++ private fun isKeyword(text: String): Boolean {",Backticks can also be used to enclose identifiers containing spaces and other characters not allowed in Java identifiers. In this case they must not be highlighted as redundant.,2017-08-03 11:04:43 +944,"@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RemoveRedundantBackticksInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ val nameIdentifier = property.nameIdentifier ?: return ++ if (isRedundantBackticks(nameIdentifier)) { ++ registerProblem(holder, nameIdentifier) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ function.valueParameters.map { ++ val nameIdentifier = it.nameIdentifier ?: return@map ++ if (isRedundantBackticks(nameIdentifier)) { ++ registerProblem(holder, nameIdentifier) ++ } ++ } ++ } ++ ++ override fun visitReferenceExpression(expression: KtReferenceExpression) { ++ super.visitReferenceExpression(expression) ++ val bindingContext = expression.analyze() ++ expression.getResolvedCall(bindingContext) ?: return ++ if (isRedundantBackticks(expression)) { ++ registerProblem(holder, expression) ++ } ++ } ++ } ++ } ++ ++ private fun isKeyword(text: String): Boolean { ++ return (KtTokens.KEYWORDS.types + KtTokens.SOFT_KEYWORDS.types).any { it.toString() == text } ++ } ++ ++ private fun isRedundantBackticks(element: PsiElement): Boolean { ++ return (element.text.contains(""^`.+`$"".toRegex()) &&",Please don't use regular expressions here. Use `startsWith` and `endsWith`.,2017-08-03 10:59:26 +945,"@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElement ++import com.intellij.psi.PsiElementVisitor ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RemoveRedundantBackticksInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ val nameIdentifier = property.nameIdentifier ?: return ++ if (isRedundantBackticks(nameIdentifier)) { ++ registerProblem(holder, nameIdentifier) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ function.valueParameters.map { ++ val nameIdentifier = it.nameIdentifier ?: return@map ++ if (isRedundantBackticks(nameIdentifier)) { ++ registerProblem(holder, nameIdentifier) ++ } ++ } ++ } ++ ++ override fun visitReferenceExpression(expression: KtReferenceExpression) { ++ super.visitReferenceExpression(expression) ++ val bindingContext = expression.analyze() ++ expression.getResolvedCall(bindingContext) ?: return ++ if (isRedundantBackticks(expression)) { ++ registerProblem(holder, expression) ++ } ++ } ++ } ++ } ++ ++ private fun isKeyword(text: String): Boolean { ++ return (KtTokens.KEYWORDS.types + KtTokens.SOFT_KEYWORDS.types).any { it.toString() == text } ++ } ++ ++ private fun isRedundantBackticks(element: PsiElement): Boolean { ++ return (element.text.contains(""^`.+`$"".toRegex()) && ++ !isKeyword(element.text.removePrefix(""`"").removeSuffix(""`""))) ++ } ++ ++ private fun registerProblem(holder: ProblemsHolder, element: PsiElement) { ++ holder.registerProblem(element, ++ ""Remove redundant backticks"", ++ ProblemHighlightType.GENERIC_ERROR_OR_WARNING, ++ RemoveRedundantBackticksQuickFix()) ++ } ++} ++ ++class RemoveRedundantBackticksQuickFix : LocalQuickFix { ++ override fun getName() = ""Remove redundant backticks"" ++ override fun getFamilyName() = name ++ ++ override fun applyFix(project: Project, descriptor: ProblemDescriptor) { ++ val element = descriptor.psiElement ++ val factory = KtPsiFactory(project) ++ element.replace(factory.createExpression(element.text.removePrefix(""`"").removeSuffix(""`"")))","If you replace an arbitrary element in a PSI tree (such as the name identifier of a property) with an expression, this will create an invalid PSI structure and will break other code insight features until the file contents is reparsed. You need to always replace an element with another element of the same type (in this case, an identifier with an identifier). Use `KtPsiFactory.createIdentifier()`.",2017-08-03 11:02:32 +41,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.psi.JetParameter; ++import org.jetbrains.jet.lang.psi.JetPsiFactory; ++import org.jetbrains.jet.lang.psi.JetTypeReference; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class ChangeTypeFix extends JetIntentionAction { ++ private JetType type;","Field may be 'final' +",2013-04-17 09:37:49 +44,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.psi.JetParameter; ++import org.jetbrains.jet.lang.psi.JetPsiFactory; ++import org.jetbrains.jet.lang.psi.JetTypeReference; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class ChangeTypeFix extends JetIntentionAction { ++ private JetType type; ++ ++ public ChangeTypeFix(@NotNull JetTypeReference element, JetType type) { ++ super(element); ++ this.type = type; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""change.type"", element.getText(), type); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""change.type.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ element.replace(JetPsiFactory.createType(project, type.toString())); ++ } ++ ++ @NotNull ++ public static JetIntentionActionFactory createFactoryForExpectedParameterTypeMismatch() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetParameter property = QuickFixUtil.getParentElementOfType(diagnostic, JetParameter.class);","Add please checking for diagnostic factory. Look like line 91 in `idea/src/org/jetbrains/jet/plugin/quickfix/AddStarProjectionsFix.java` +",2013-04-17 10:12:08 +42,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.psi.JetParameter; ++import org.jetbrains.jet.lang.psi.JetPsiFactory; ++import org.jetbrains.jet.lang.psi.JetTypeReference; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class ChangeTypeFix extends JetIntentionAction { ++ private JetType type; ++ ++ public ChangeTypeFix(@NotNull JetTypeReference element, JetType type) { ++ super(element); ++ this.type = type; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""change.type"", element.getText(), type); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""change.type.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ element.replace(JetPsiFactory.createType(project, type.toString())); ++ } ++ ++ @NotNull ++ public static JetIntentionActionFactory createFactoryForExpectedParameterTypeMismatch() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetParameter property = QuickFixUtil.getParentElementOfType(diagnostic, JetParameter.class); ++ assert property != null : ""EXPECTED_PARAMETER_TYPE_MISMATCH reported on element that is not within any property""; ++ JetTypeReference typeReference = property.getTypeReference(); ++ JetType type = ((DiagnosticWithParameters1) diagnostic).getA();","Use SuppressWarnings, please, like line 92-95 in `idea/src/org/jetbrains/jet/plugin/quickfix/AddStarProjectionsFix.java` +",2013-04-17 09:41:37 +45,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.psi.JetParameter; ++import org.jetbrains.jet.lang.psi.JetPsiFactory; ++import org.jetbrains.jet.lang.psi.JetTypeReference; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class ChangeTypeFix extends JetIntentionAction { ++ private JetType type; ++ ++ public ChangeTypeFix(@NotNull JetTypeReference element, JetType type) { ++ super(element); ++ this.type = type; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""change.type"", element.getText(), type); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""change.type.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ element.replace(JetPsiFactory.createType(project, type.toString())); ++ } ++ ++ @NotNull ++ public static JetIntentionActionFactory createFactoryForExpectedParameterTypeMismatch() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetParameter property = QuickFixUtil.getParentElementOfType(diagnostic, JetParameter.class); ++ assert property != null : ""EXPECTED_PARAMETER_TYPE_MISMATCH reported on element that is not within any property""; ++ JetTypeReference typeReference = property.getTypeReference(); ++ JetType type = ((DiagnosticWithParameters1) diagnostic).getA(); ++ return typeReference == null ? null : new ChangeTypeFix(typeReference, type);","Maybe `typeReference == null` should be just `assert` +",2013-04-17 11:05:31 +43,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2013 JetBrains s.r.o. ++ * ++ * Licensed under the Apache License, Version 2.0 (the ""License""); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an ""AS IS"" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package org.jetbrains.jet.plugin.quickfix; ++ ++import com.intellij.codeInsight.intention.IntentionAction; ++import com.intellij.openapi.editor.Editor; ++import com.intellij.openapi.project.Project; ++import com.intellij.psi.PsiFile; ++import com.intellij.util.IncorrectOperationException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.jet.lang.diagnostics.Diagnostic; ++import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; ++import org.jetbrains.jet.lang.psi.JetParameter; ++import org.jetbrains.jet.lang.psi.JetPsiFactory; ++import org.jetbrains.jet.lang.psi.JetTypeReference; ++import org.jetbrains.jet.lang.types.JetType; ++import org.jetbrains.jet.plugin.JetBundle; ++ ++public class ChangeTypeFix extends JetIntentionAction { ++ private JetType type; ++ ++ public ChangeTypeFix(@NotNull JetTypeReference element, JetType type) { ++ super(element); ++ this.type = type; ++ } ++ ++ @NotNull ++ @Override ++ public String getText() { ++ return JetBundle.message(""change.type"", element.getText(), type); ++ } ++ ++ @NotNull ++ @Override ++ public String getFamilyName() { ++ return JetBundle.message(""change.type.family""); ++ } ++ ++ @Override ++ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ++ element.replace(JetPsiFactory.createType(project, type.toString())); ++ } ++ ++ @NotNull ++ public static JetIntentionActionFactory createFactoryForExpectedParameterTypeMismatch() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetParameter property = QuickFixUtil.getParentElementOfType(diagnostic, JetParameter.class); ++ assert property != null : ""EXPECTED_PARAMETER_TYPE_MISMATCH reported on element that is not within any property""; ++ JetTypeReference typeReference = property.getTypeReference(); ++ JetType type = ((DiagnosticWithParameters1) diagnostic).getA(); ++ return typeReference == null ? null : new ChangeTypeFix(typeReference, type); ++ } ++ }; ++ } ++ ++ @NotNull ++ public static JetIntentionActionFactory createFactoryForExpectedReturnTypeMismatch() { ++ return new JetIntentionActionFactory() { ++ @Nullable ++ @Override ++ public IntentionAction createAction(Diagnostic diagnostic) { ++ JetTypeReference typeReference = QuickFixUtil.getParentElementOfType(diagnostic, JetTypeReference.class); ++ assert typeReference != null : ""EXPECTED_RETURN_TYPE_MISMATCH reported on element that is not a type reference""; ++ JetType type = ((DiagnosticWithParameters1) diagnostic).getA();","Use SuppressWarnings, please. +",2013-04-17 09:41:54 +215,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import com.intellij.psi.util.PsiTreeUtil ++import com.intellij.psi.PsiDocumentManager ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.di.InjectorForMacros ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.types.TypeUtils ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import com.intellij.codeInsight.template.TemplateBuilderImpl ++import com.intellij.codeInsight.template.impl.TemplateManagerImpl ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++import org.jetbrains.jet.lang.descriptors.ModuleDescriptor ++ ++ ++public class AddForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""add.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val loopRange = element.getLoopRange()!! ++ val newRangeText = ""${loopRange.getText()}.withIndices()"" ++ val newRange = JetPsiFactory.createExpression(editor.getProject(), newRangeText) ++ ++ //Roundabout way to create new multiparameter element so as not to incorrectly trigger syntax error highlighting ++ val loopParameter = element.getLoopParameter()!! ++ val parenthesizedParam = JetPsiFactory.createExpression(editor.getProject(), ""(index)"") as JetParenthesizedExpression ++ val indexElement = parenthesizedParam.getExpression()!! ++ val comma = JetPsiFactory.createComma(editor.getProject()) ++ val newParamElement = JetPsiFactory.createExpression(editor.getProject(), "" ${loopParameter.getText()}"") ++ parenthesizedParam.addAfter(newParamElement, indexElement) ++ parenthesizedParam.addAfter(comma, indexElement) ++ ++ loopParameter.replace(parenthesizedParam) ++ loopRange.replace(newRange) ++ ++ val multiParameter = PsiTreeUtil.findChildOfType(element, indexElement.javaClass)!! ++ ++ editor.getCaretModel().moveToOffset(multiParameter.getTextOffset()) ++ val templateBuilder = TemplateBuilderImpl(multiParameter) ++ templateBuilder.replaceElement(multiParameter, ""index"") ++ val manager = TemplateManagerImpl(editor.getProject()) ++ PsiDocumentManager.getInstance(editor.getProject()!!).doPostponedOperationsAndUnblockDocument(editor.getDocument()) ++ manager.startTemplate(editor, templateBuilder.buildInlineTemplate()!!) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getLoopParameter() == null) return false ++ val range = element.getLoopRange() ?: return false ++ if (range is JetDotQualifiedExpression) { ++ val selector = (range as JetDotQualifiedExpression).getSelectorExpression() ?: return true","You don't need this cast (experience the power of Kotlin) +",2014-04-30 18:55:57 +216,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import com.intellij.psi.util.PsiTreeUtil ++import com.intellij.psi.PsiDocumentManager ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.di.InjectorForMacros ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.types.TypeUtils ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import com.intellij.codeInsight.template.TemplateBuilderImpl ++import com.intellij.codeInsight.template.impl.TemplateManagerImpl ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++import org.jetbrains.jet.lang.descriptors.ModuleDescriptor ++ ++ ++public class AddForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""add.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val loopRange = element.getLoopRange()!! ++ val newRangeText = ""${loopRange.getText()}.withIndices()"" ++ val newRange = JetPsiFactory.createExpression(editor.getProject(), newRangeText) ++ ++ //Roundabout way to create new multiparameter element so as not to incorrectly trigger syntax error highlighting ++ val loopParameter = element.getLoopParameter()!! ++ val parenthesizedParam = JetPsiFactory.createExpression(editor.getProject(), ""(index)"") as JetParenthesizedExpression ++ val indexElement = parenthesizedParam.getExpression()!! ++ val comma = JetPsiFactory.createComma(editor.getProject()) ++ val newParamElement = JetPsiFactory.createExpression(editor.getProject(), "" ${loopParameter.getText()}"") ++ parenthesizedParam.addAfter(newParamElement, indexElement) ++ parenthesizedParam.addAfter(comma, indexElement) ++ ++ loopParameter.replace(parenthesizedParam) ++ loopRange.replace(newRange) ++ ++ val multiParameter = PsiTreeUtil.findChildOfType(element, indexElement.javaClass)!! ++ ++ editor.getCaretModel().moveToOffset(multiParameter.getTextOffset()) ++ val templateBuilder = TemplateBuilderImpl(multiParameter) ++ templateBuilder.replaceElement(multiParameter, ""index"") ++ val manager = TemplateManagerImpl(editor.getProject()) ++ PsiDocumentManager.getInstance(editor.getProject()!!).doPostponedOperationsAndUnblockDocument(editor.getDocument()) ++ manager.startTemplate(editor, templateBuilder.buildInlineTemplate()!!) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getLoopParameter() == null) return false ++ val range = element.getLoopRange() ?: return false ++ if (range is JetDotQualifiedExpression) { ++ val selector = (range as JetDotQualifiedExpression).getSelectorExpression() ?: return true ++ if (selector.getText().equals(""withIndices()"")) return false","Please use `==` instead of `equals` in Kotlin code +",2014-04-30 18:56:26 +212,"@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import com.intellij.psi.util.PsiTreeUtil ++import com.intellij.psi.PsiDocumentManager ++import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache ++import org.jetbrains.jet.di.InjectorForMacros ++import org.jetbrains.jet.lang.resolve.BindingContext ++import org.jetbrains.jet.lang.types.TypeUtils ++import org.jetbrains.jet.lang.resolve.ObservableBindingTrace ++import org.jetbrains.jet.lang.resolve.BindingTraceContext ++import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo ++import org.jetbrains.jet.lang.psi.JetParenthesizedExpression ++import com.intellij.codeInsight.template.TemplateBuilderImpl ++import com.intellij.codeInsight.template.impl.TemplateManagerImpl ++import org.jetbrains.jet.lang.resolve.DescriptorUtils ++import org.jetbrains.jet.lang.descriptors.ModuleDescriptor ++ ++ ++public class AddForLoopIndicesIntention : JetSelfTargetingIntention( ++ ""add.for.loop.indices"", javaClass()) { ++ override fun applyTo(element: JetForExpression, editor: Editor) { ++ val loopRange = element.getLoopRange()!! ++ val newRangeText = ""${loopRange.getText()}.withIndices()"" ++ val newRange = JetPsiFactory.createExpression(editor.getProject(), newRangeText) ++ ++ //Roundabout way to create new multiparameter element so as not to incorrectly trigger syntax error highlighting ++ val loopParameter = element.getLoopParameter()!! ++ val parenthesizedParam = JetPsiFactory.createExpression(editor.getProject(), ""(index)"") as JetParenthesizedExpression ++ val indexElement = parenthesizedParam.getExpression()!! ++ val comma = JetPsiFactory.createComma(editor.getProject()) ++ val newParamElement = JetPsiFactory.createExpression(editor.getProject(), "" ${loopParameter.getText()}"") ++ parenthesizedParam.addAfter(newParamElement, indexElement) ++ parenthesizedParam.addAfter(comma, indexElement) ++ ++ loopParameter.replace(parenthesizedParam) ++ loopRange.replace(newRange) ++ ++ val multiParameter = PsiTreeUtil.findChildOfType(element, indexElement.javaClass)!! ++ ++ editor.getCaretModel().moveToOffset(multiParameter.getTextOffset()) ++ val templateBuilder = TemplateBuilderImpl(multiParameter) ++ templateBuilder.replaceElement(multiParameter, ""index"") ++ val manager = TemplateManagerImpl(editor.getProject()) ++ PsiDocumentManager.getInstance(editor.getProject()!!).doPostponedOperationsAndUnblockDocument(editor.getDocument()) ++ manager.startTemplate(editor, templateBuilder.buildInlineTemplate()!!) ++ } ++ ++ override fun isApplicableTo(element: JetForExpression): Boolean { ++ if (element.getLoopParameter() == null) return false ++ val range = element.getLoopRange() ?: return false ++ if (range is JetDotQualifiedExpression) { ++ val selector = (range as JetDotQualifiedExpression).getSelectorExpression() ?: return true ++ if (selector.getText().equals(""withIndices()"")) return false ++ } ++ ++ val potentialExpression = JetPsiFactory.createExpression(element.getProject(), ""${range.getText()}.withIndices()"") ++ val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element) ++ val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, element] ?: return false ++ val module = DescriptorUtils.getParentOfType(scope.getContainingDeclaration(), javaClass())!! ++ val components = InjectorForMacros(element.getProject(), module) ++ val dataFlowInfo = bindingContext[BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW, element] ?: DataFlowInfo.EMPTY ++ val bindingTrace = ObservableBindingTrace(BindingTraceContext()) ++ val expressionType = components.getExpressionTypingServices()!!.getTypeInfo(scope, potentialExpression, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, bindingTrace) ++ return expressionType.getType() != null","Do you allow to use the intention only if the resulting code will be green? In that case, I'm not sure what's wrong, but it's still applicable whenever there are errors in the initial code, e.g. + +``` +fun foo() { + for (a in b) { // <-- still applicable here, although 'b' is unresolved + } +} +``` +",2014-04-30 18:12:56 +883,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.impl.source.tree.LeafPsiElement ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.imports.importableFqName ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RedundantProgressionStepInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (isStepOneCall(expression)) { ++ holder.registerProblem(expression, ++ ""Iteration step is redundant. Recommended to remove it."",","No need to say ""Recommended..."" in the problem description; ""redundant"" implies that already.",2017-07-07 11:46:31 +886,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.impl.source.tree.LeafPsiElement ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.imports.importableFqName ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RedundantProgressionStepInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (isStepOneCall(expression)) { ++ holder.registerProblem(expression, ++ ""Iteration step is redundant. Recommended to remove it."", ++ ProblemHighlightType.WEAK_WARNING, ++ TextRange(expression.operationReference.startOffsetInParent, expression.endOffset - expression.startOffset), ++ EliminateStepOneFix()) ++ } ++ } ++ } ++ } ++ ++ ++ class EliminateStepOneFix : LocalQuickFix { ++ override fun getName() = ""Eliminate redundant iteration step size"" ++ ++ override fun getFamilyName() = name ++ ++ override fun applyFix(project: Project, descriptor: ProblemDescriptor) { ++ if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.psiElement)) return ++ val expression = descriptor.psiElement as? KtBinaryExpression ?: return","This only handles ""step"" called as an infix function; would be better to handle regular ""step"" calls too.",2017-07-07 11:54:53 +885,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.impl.source.tree.LeafPsiElement ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.imports.importableFqName ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RedundantProgressionStepInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (isStepOneCall(expression)) { ++ holder.registerProblem(expression, ++ ""Iteration step is redundant. Recommended to remove it."", ++ ProblemHighlightType.WEAK_WARNING, ++ TextRange(expression.operationReference.startOffsetInParent, expression.endOffset - expression.startOffset), ++ EliminateStepOneFix()) ++ } ++ } ++ } ++ } ++ ++ ++ class EliminateStepOneFix : LocalQuickFix { ++ override fun getName() = ""Eliminate redundant iteration step size"" ++ ++ override fun getFamilyName() = name ++ ++ override fun applyFix(project: Project, descriptor: ProblemDescriptor) { ++ if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.psiElement)) return ++ val expression = descriptor.psiElement as? KtBinaryExpression ?: return ++ if (!isStepOneCall(expression)) return ++ expression.replaced(expression.left!!) ++ } ++ } ++ ++ companion object { ++ private val STEP_FUNCTION_FQ_NAME = ""kotlin.ranges.step"" ++ ++ fun isStepOneCall(expression: KtBinaryExpression): Boolean { ++ val left = expression.left as? KtBinaryExpression ?: return false",You should use KtPsiUtil.deparenthesize() to handle the case when the range expression is in parentheses.,2017-07-07 11:53:29 +884,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import com.intellij.openapi.util.TextRange ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.impl.source.tree.LeafPsiElement ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.idea.imports.importableFqName ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.KtBinaryExpression ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtVisitorVoid ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.psi.psiUtil.startOffset ++import org.jetbrains.kotlin.resolve.BindingContext ++import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall ++ ++class RedundantProgressionStepInspection : AbstractKotlinInspection() { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitBinaryExpression(expression: KtBinaryExpression) { ++ if (isStepOneCall(expression)) { ++ holder.registerProblem(expression, ++ ""Iteration step is redundant. Recommended to remove it."", ++ ProblemHighlightType.WEAK_WARNING, ++ TextRange(expression.operationReference.startOffsetInParent, expression.endOffset - expression.startOffset), ++ EliminateStepOneFix()) ++ } ++ } ++ } ++ } ++ ++ ++ class EliminateStepOneFix : LocalQuickFix { ++ override fun getName() = ""Eliminate redundant iteration step size"" ++ ++ override fun getFamilyName() = name ++ ++ override fun applyFix(project: Project, descriptor: ProblemDescriptor) { ++ if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.psiElement)) return ++ val expression = descriptor.psiElement as? KtBinaryExpression ?: return ++ if (!isStepOneCall(expression)) return ++ expression.replaced(expression.left!!) ++ } ++ } ++ ++ companion object { ++ private val STEP_FUNCTION_FQ_NAME = ""kotlin.ranges.step"" ++ ++ fun isStepOneCall(expression: KtBinaryExpression): Boolean { ++ val left = expression.left as? KtBinaryExpression ?: return false ++ if (left.operationToken != KtTokens.RANGE) return false ++ if (expression.operationReference.text != ""step"") return false ++ val right = expression.right as? KtConstantExpression ?: return false ++ val rightConst = right.firstChild as? LeafPsiElement ?: return false ++ if (rightConst.elementType != KtTokens.INTEGER_LITERAL) return false ++ ++ if (rightConst.text !in setOf(""1"", ""1L"")) return false",Please use ConstantExpressionEvaluator.getConstant() instead.,2017-07-07 11:51:57 +854,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.LocalQuickFix ++import com.intellij.codeInspection.ProblemDescriptor ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.addRemoveModifier.addModifier ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.isInheritable ++import org.jetbrains.kotlin.psi.psiUtil.isOverridable ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) {","This should check val/var parameters defined in the primary constructor, too (KtParameter)",2017-05-16 15:24:22 +855,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.LocalQuickFix ++import com.intellij.codeInspection.ProblemDescriptor ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.addRemoveModifier.addModifier ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.isInheritable ++import org.jetbrains.kotlin.psi.psiUtil.isOverridable ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ if (canBePrivate(property)) { ++ registerProblem(holder, property) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (canBePrivate(function)) { ++ registerProblem(holder, function) ++ } ++ } ++ } ++ } ++ ++ ++ private fun canBePrivate(declaration: KtDeclaration): Boolean { ++ val modifiers = declaration.modifierList ++ if (modifiers != null && (modifiers.hasModifier(KtTokens.PRIVATE_KEYWORD) || modifiers.hasModifier(KtTokens.OVERRIDE_KEYWORD))) return false",You can use `declaration.hasModifier()` directly,2017-05-16 15:24:55 +856,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.LocalQuickFix ++import com.intellij.codeInspection.ProblemDescriptor ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.addRemoveModifier.addModifier ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.isInheritable ++import org.jetbrains.kotlin.psi.psiUtil.isOverridable ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ if (canBePrivate(property)) { ++ registerProblem(holder, property) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (canBePrivate(function)) { ++ registerProblem(holder, function) ++ } ++ } ++ } ++ } ++ ++ ++ private fun canBePrivate(declaration: KtDeclaration): Boolean { ++ val modifiers = declaration.modifierList ++ if (modifiers != null && (modifiers.hasModifier(KtTokens.PRIVATE_KEYWORD) || modifiers.hasModifier(KtTokens.OVERRIDE_KEYWORD))) return false ++ val klass = (declaration.parent as? KtClassBody)?.parent as? KtClass ?: return false ++ if (!klass.isInheritable() && modifiers?.hasModifier(KtTokens.PROTECTED_KEYWORD) ?: false) return false //reported by ProtectedInFinalInspection ++ if (declaration.isOverridable()) return false ++ val allUsages = ReferencesSearch.search(declaration, declaration.useScope).count()","This is very inefficient: usages search is an expensive operation and most of the cost is wasted. You should iterate over all usages and stop as soon as you find one outside the local search scope. + +See also the [corresponding Java inspection](https://github.com/JetBrains/intellij-community/blob/master/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/AccessCanBeTightenedInspection.java#L143) for inspiration.",2017-05-16 15:28:33 +857,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInsight.FileModificationService ++import com.intellij.codeInspection.LocalQuickFix ++import com.intellij.codeInspection.ProblemDescriptor ++import com.intellij.codeInspection.ProblemHighlightType ++import com.intellij.codeInspection.ProblemsHolder ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.addRemoveModifier.addModifier ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.isInheritable ++import org.jetbrains.kotlin.psi.psiUtil.isOverridable ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ if (canBePrivate(property)) { ++ registerProblem(holder, property) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (canBePrivate(function)) { ++ registerProblem(holder, function) ++ } ++ } ++ } ++ } ++ ++ ++ private fun canBePrivate(declaration: KtDeclaration): Boolean { ++ val modifiers = declaration.modifierList ++ if (modifiers != null && (modifiers.hasModifier(KtTokens.PRIVATE_KEYWORD) || modifiers.hasModifier(KtTokens.OVERRIDE_KEYWORD))) return false ++ val klass = (declaration.parent as? KtClassBody)?.parent as? KtClass ?: return false ++ if (!klass.isInheritable() && modifiers?.hasModifier(KtTokens.PROTECTED_KEYWORD) ?: false) return false //reported by ProtectedInFinalInspection ++ if (declaration.isOverridable()) return false ++ val allUsages = ReferencesSearch.search(declaration, declaration.useScope).count() ++ if (allUsages == 0) return false ++ val classUsages = ReferencesSearch.search(declaration, LocalSearchScope(klass)).count() ++ if (allUsages != classUsages) ++ return false ++ return true ++ } ++ ++ private fun registerProblem(holder: ProblemsHolder, declaration: KtDeclaration) { ++ holder.registerProblem(declaration, ++ ""Can have 'private' visibility"", ++ ProblemHighlightType.WEAK_WARNING, ++ MakePrivateFix()) ++ } ++ ++ class MakePrivateFix : LocalQuickFix {",You can reuse `AddModifierFix`,2017-05-16 15:29:31 +858,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.PsiReference ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import com.intellij.util.Processor ++import org.jetbrains.kotlin.idea.quickfix.AddModifierFix ++import org.jetbrains.kotlin.idea.refactoring.isConstructorDeclaredProperty ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.isInheritable ++import org.jetbrains.kotlin.psi.psiUtil.isOverridable ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ if (canBePrivate(property)) {",This is now reported on local variables (which are also KtProperty instances).,2017-05-19 18:28:28 +859,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.PsiReference ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import com.intellij.util.Processor ++import org.jetbrains.kotlin.idea.quickfix.AddModifierFix ++import org.jetbrains.kotlin.idea.refactoring.isConstructorDeclaredProperty ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.isInheritable ++import org.jetbrains.kotlin.psi.psiUtil.isOverridable ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ if (canBePrivate(property)) { ++ registerProblem(holder, property) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (canBePrivate(function)) { ++ registerProblem(holder, function) ++ } ++ } ++ ++ override fun visitParameter(parameter: KtParameter) { ++ super.visitParameter(parameter) ++ if (parameter.isConstructorDeclaredProperty() && canBePrivate(parameter)) { ++ registerProblem(holder, parameter) ++ } ++ } ++ } ++ } ++ ++ ++ private fun canBePrivate(declaration: KtDeclaration): Boolean { ++ if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false ++ val klass = declaration.containingClass() ?: return false",Wouldn't hurt to handle members of `object` declarations too.,2017-05-19 18:28:48 +860,"@@ -0,0 +1,89 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.PsiReference ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import com.intellij.util.Processor ++import org.jetbrains.kotlin.idea.quickfix.AddModifierFix ++import org.jetbrains.kotlin.idea.refactoring.isConstructorDeclaredProperty ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.containingClass ++import org.jetbrains.kotlin.psi.psiUtil.getParentOfType ++import org.jetbrains.kotlin.psi.psiUtil.isInheritable ++import org.jetbrains.kotlin.psi.psiUtil.isOverridable ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ if (canBePrivate(property)) { ++ registerProblem(holder, property) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (canBePrivate(function)) { ++ registerProblem(holder, function) ++ } ++ } ++ ++ override fun visitParameter(parameter: KtParameter) { ++ super.visitParameter(parameter) ++ if (parameter.isConstructorDeclaredProperty() && canBePrivate(parameter)) { ++ registerProblem(holder, parameter) ++ } ++ } ++ } ++ } ++ ++ ++ private fun canBePrivate(declaration: KtDeclaration): Boolean { ++ if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false ++ val klass = declaration.containingClass() ?: return false ++ if (!klass.isInheritable() && declaration.hasModifier(KtTokens.PROTECTED_KEYWORD)) return false //reported by ProtectedInFinalInspection ++ if (declaration.isOverridable()) return false ++ var otherUsageFound = false ++ var inClassUsageFound = false ++ ReferencesSearch.search(declaration, declaration.useScope).forEach(Processor { ++ val usage = it.element ++ if (klass != usage.getParentOfType(false)) { ++ otherUsageFound = true ++ false ++ } else { ++ inClassUsageFound = true ++ true ++ } ++ }) ++ return inClassUsageFound && !otherUsageFound ++ } ++ ++ private fun registerProblem(holder: ProblemsHolder, declaration: KtDeclaration) { ++ val modifierListOwner = declaration.getParentOfType(false) ?: return ++ holder.registerProblem(declaration, ++ ""Can have 'private' visibility"",","Better to include name of declaration in the message, otherwise it's hard to understand results of a batch inspection.",2017-05-19 18:29:34 +852,"@@ -0,0 +1,9 @@ ++// IS_APPLICABLE: false ++// WITH_RUNTIME ++class A(val _value: Int) { ++ operator fun compareTo(other: Int) = _value.compareTo(other) ++} ++ ++fun test(a: A): Boolean { ++ return a >= 0 && a <= 100","My suggested change to KotlinType.isComparable() will break this test, but I think it's OK because this test should be red, and we make no guarantees regarding the behavior of intentions on red code.",2017-05-08 13:11:43 +230,"@@ -0,0 +1,9 @@ ++// WITH_RUNTIME ++// IS_APPLICABLE: FALSE ++fun String.withIndices(): Int = 42 ++ ++fun foo(s: String) { ++ for (a in s) { ++ ++ } ++}","The test is fine, the naming is not: _overridden_ function is a function declaration in a subclass with the same signature as in the superclass. There are no overridden functions here, `withIndices` is just an extension function +",2014-05-12 12:39:33 +853,"@@ -0,0 +1,9 @@ ++interface B { ++ fun c() ++} ++ ++ ++object A : B {",This should be `object a`,2017-05-08 13:29:17 +424,"@@ -0,0 +1,91 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.service ++ ++import java.io.FilePermission ++import java.net.SocketPermission ++import java.security.CodeSource ++import java.security.Permission ++import java.security.PermissionCollection ++import java.security.Policy ++import java.util.ArrayList ++import java.util.Collections ++import java.util.Enumeration ++import java.util.PropertyPermission ++ ++ ++public class DaemonPolicy(val port: Int) : Policy() { ++ ++ private fun createPermissions(): PermissionCollection { ++ val perms = DaemonPermissionCollection() ++ ++ val socketPermission = SocketPermission(""localhost:$port-"", ""connect, accept, resolve"") ++ val propertyPermission = PropertyPermission(""localhost:$port"", ""read"") ++ //val filePermission = FilePermission(""<>"", ""read"") ++ ++ perms.add(socketPermission) ++ perms.add(propertyPermission) ++ //perms.add(filePermission) ++ ++ return perms ++ } ++ ++ private val perms: PermissionCollection by lazy { createPermissions() } ++ ++ override fun getPermissions(codesource: CodeSource?): PermissionCollection { ++ return perms ++ } ++} ++ ++ ++class DaemonPermissionCollection : PermissionCollection() { ++ var perms = ArrayList()","why `var`? +",2015-08-20 14:45:43 +423,"@@ -0,0 +1,91 @@ ++/* ++ * Copyright 2010-2015 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.kotlin.rmi.service ++ ++import java.io.FilePermission ++import java.net.SocketPermission ++import java.security.CodeSource ++import java.security.Permission ++import java.security.PermissionCollection ++import java.security.Policy ++import java.util.ArrayList ++import java.util.Collections ++import java.util.Enumeration ++import java.util.PropertyPermission ++ ++ ++public class DaemonPolicy(val port: Int) : Policy() { ++ ++ private fun createPermissions(): PermissionCollection { ++ val perms = DaemonPermissionCollection() ++ ++ val socketPermission = SocketPermission(""localhost:$port-"", ""connect, accept, resolve"") ++ val propertyPermission = PropertyPermission(""localhost:$port"", ""read"") ++ //val filePermission = FilePermission(""<>"", ""read"") ++ ++ perms.add(socketPermission) ++ perms.add(propertyPermission) ++ //perms.add(filePermission) ++ ++ return perms ++ } ++ ++ private val perms: PermissionCollection by lazy { createPermissions() } ++ ++ override fun getPermissions(codesource: CodeSource?): PermissionCollection { ++ return perms ++ } ++} ++ ++ ++class DaemonPermissionCollection : PermissionCollection() { ++ var perms = ArrayList() ++ ++ override fun add(p: Permission) { ++ perms.add(p) ++ } ++ ++ override fun implies(p: Permission): Boolean { ++ val i = perms.iterator()","perms.any { it.implies(p) } +",2015-08-20 14:45:27 +864,"@@ -0,0 +1,91 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.psi.PsiElementVisitor ++import com.intellij.psi.PsiReference ++import com.intellij.psi.search.LocalSearchScope ++import com.intellij.psi.search.searches.ReferencesSearch ++import com.intellij.util.Processor ++import org.jetbrains.kotlin.idea.quickfix.AddModifierFix ++import org.jetbrains.kotlin.idea.refactoring.isConstructorDeclaredProperty ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.* ++ ++class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { ++ ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { ++ return object : KtVisitorVoid() { ++ override fun visitProperty(property: KtProperty) { ++ super.visitProperty(property) ++ if (!property.isLocal && canBePrivate(property)) { ++ registerProblem(holder, property) ++ } ++ } ++ ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (canBePrivate(function)) { ++ registerProblem(holder, function) ++ } ++ } ++ ++ override fun visitParameter(parameter: KtParameter) { ++ super.visitParameter(parameter) ++ if (parameter.isConstructorDeclaredProperty() && canBePrivate(parameter)) { ++ registerProblem(holder, parameter) ++ } ++ } ++ } ++ } ++ ++ ++ private fun canBePrivate(declaration: KtDeclaration): Boolean { ++ if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false ++ val classOrObject = declaration.containingClassOrObject ?: return false ++ val inheritable = classOrObject is KtClass && classOrObject.isInheritable() ++ if (!inheritable && declaration.hasModifier(KtTokens.PROTECTED_KEYWORD)) return false //reported by ProtectedInFinalInspection ++ if (declaration.isOverridable()) return false ++ var otherUsageFound = false ++ var inClassUsageFound = false ++ ReferencesSearch.search(declaration, declaration.useScope).forEach(Processor { ++ val usage = it.element ++ if (classOrObject != usage.getParentOfType(false)) { ++ otherUsageFound = true ++ false ++ } else { ++ inClassUsageFound = true ++ true ++ } ++ }) ++ return inClassUsageFound && !otherUsageFound ++ } ++ ++ private fun registerProblem(holder: ProblemsHolder, declaration: KtDeclaration) { ++ val modifierListOwner = declaration.getParentOfType(false) ?: return ++ val member = when (declaration) { ++ is KtNamedFunction -> ""Function"" ++ else -> ""Property"" ++ } ++ holder.registerProblem(declaration,","This highlights the entire declaration with a wavy underline, which is very intrusive. Should highlight only the name identifier.",2017-05-23 17:08:14 +985,"@@ -0,0 +1,92 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.effectsystem.impls ++ ++import org.jetbrains.kotlin.effectsystem.structure.ESClause ++import org.jetbrains.kotlin.effectsystem.structure.EffectSchema ++import org.jetbrains.kotlin.effectsystem.structure.ESExpressionVisitor ++ ++class Printer : ESExpressionVisitor { ++ private val builder = StringBuilder() ++ ++ private fun print(string: String) { ++ builder.append(string) ++ } ++ ++ private inline fun line(block: () -> Unit) { ++ block() ++ } ++ ++ fun print(schema: EffectSchema) { ++ schema.clauses.forEach { visitClause(it) } ++ } ++ ++ fun visitClause(clause: ESClause) { ++ line { ++ clause.condition.accept(this) ++ print("" -> "")",Looks like this arrow has the wrong direction,2017-08-15 16:54:12 +196,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ return hasExplicitReturnType(element) || hasExplicitReceiverType(element) || hasExplicitParamType(element) ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ val oldParameters = oldParameterList?.getParameters() ++ if (oldParameterList != null && oldParameters != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameters.map({(parameter: JetParameter): String -> parameter.getNameIdentifier()!!.getText()!!","Your intention would be helpful to make types implicit here :) I think they don't really add anything to readability +",2014-04-22 22:25:02 +195,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ return hasExplicitReturnType(element) || hasExplicitReceiverType(element) || hasExplicitParamType(element) ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ val oldParameters = oldParameterList?.getParameters() ++ if (oldParameterList != null && oldParameters != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameters.map({(parameter: JetParameter): String -> parameter.getNameIdentifier()!!.getText()!! ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ oldParameterList.replace(newParameterList) ++ } ++ ++ if (!hasExplicitParamType(element)) { ++ val currentParamList = element.getFunctionLiteral().getValueParameterList() ++ val firstChild = currentParamList?.getFirstChild() ++ if (firstChild?.getNode()?.getElementType() == JetTokens.LPAR) firstChild!!.delete() ++ val lastChild = currentParamList?.getLastChild() ++ if (lastChild?.getNode()?.getElementType() == JetTokens.RPAR) lastChild!!.delete() ++ } ++ } ++ ++ fun hasExplicitReturnType(element: JetFunctionLiteralExpression): Boolean { ++ return element.hasDeclaredReturnType() ++ } ++ ++ fun hasExplicitReceiverType(element: JetFunctionLiteralExpression): Boolean { ++ return element.getFunctionLiteral().getReceiverTypeRef() != null ++ } ++ ++ fun hasExplicitParamType(element: JetFunctionLiteralExpression): Boolean { ++ if (element.getValueParameters().any { it.getTypeReference() != null }) { ++ val parameters = element.getFunctionLiteral().getValueParameterList()?.getParameters() ++ return !(parameters?.any { it.getNameIdentifier()?.getText() == null } ?: false)","This code looks a little awkward to me. + +First, consider using other standard library functions such as `none` or `all` instead of `any` to prevent at least some negations. + +Second, why can't you iterate the parameter list with one simple `for` and check two conditions for each parameter in the loop body? +",2014-04-22 22:12:08 +198,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ return hasExplicitReturnType(element) || hasExplicitReceiverType(element) || hasExplicitParamType(element) ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ val oldParameters = oldParameterList?.getParameters() ++ if (oldParameterList != null && oldParameters != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameters.map({(parameter: JetParameter): String -> parameter.getNameIdentifier()!!.getText()!! ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ oldParameterList.replace(newParameterList) ++ } ++ ++ if (!hasExplicitParamType(element)) { ++ val currentParamList = element.getFunctionLiteral().getValueParameterList() ++ val firstChild = currentParamList?.getFirstChild() ++ if (firstChild?.getNode()?.getElementType() == JetTokens.LPAR) firstChild!!.delete() ++ val lastChild = currentParamList?.getLastChild() ++ if (lastChild?.getNode()?.getElementType() == JetTokens.RPAR) lastChild!!.delete() ++ } ++ } ++ ++ fun hasExplicitReturnType(element: JetFunctionLiteralExpression): Boolean { ++ return element.hasDeclaredReturnType() ++ } ++ ++ fun hasExplicitReceiverType(element: JetFunctionLiteralExpression): Boolean { ++ return element.getFunctionLiteral().getReceiverTypeRef() != null ++ } ++ ++ fun hasExplicitParamType(element: JetFunctionLiteralExpression): Boolean { ++ if (element.getValueParameters().any { it.getTypeReference() != null }) { ++ val parameters = element.getFunctionLiteral().getValueParameterList()?.getParameters() ++ return !(parameters?.any { it.getNameIdentifier()?.getText() == null } ?: false) ++ } ++ return false; ++ }","Ditto (`private`) +",2014-04-22 22:25:56 +127,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import com.intellij.lang.ASTNode ++import com.intellij.psi.PsiElement ++import com.siyeh.ig.PsiReplacementUtil ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5","Stricter way is to find ""else"" keyword directly by `element.getNode().findChildByType(JetTokens.ELSE_KEYWORD)`. And this ""minus 5"" looks very esoteric anyway :) +",2014-03-04 16:04:00 +128,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import com.intellij.lang.ASTNode ++import com.intellij.psi.PsiElement ++import com.siyeh.ig.PsiReplacementUtil ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5 ++ if (caretLocation < elseLocation) { ++ expressionType = ""if"" ++ } ++ }","This code for distinguishing ""if"" from ""else"" has two problems: +- It is duplicated (here and symmetric intention) +- It is spread among two places: first `getExpressionType` returns `else` (which actually means ""if or else, I don't know yet), and then it is recalculated for if-else case. + Alternative it to pass caret position to `getExpressionType`, so all these calculations will be there. +",2014-03-04 16:05:53 +129,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import com.intellij.lang.ASTNode ++import com.intellij.psi.PsiElement ++import com.siyeh.ig.PsiReplacementUtil ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5 ++ if (caretLocation < elseLocation) { ++ expressionType = ""if"" ++ } ++ } ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ if (jetBlockElement != null) return false ++ ++ setText(""Add braces to '$expressionType' statement"") ++ return true ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val bodyNode = when (expressionType) { ++ ""else"" -> element.getNode().findChildByType(JetNodeTypes.ELSE) ++ ""if"" -> element.getNode().findChildByType(JetNodeTypes.THEN) ++ else -> element.getNode().findChildByType(JetNodeTypes.BODY) ++ } ++ generateCleanOutput(element, bodyNode) ++ } ++ ++ fun generateCleanOutput(element: JetExpressionImpl, bodyNode: ASTNode?) { ++ val newElement: PsiElement? ++ ++ if (element.getNextSibling()?.getText() == "";"") { ++ element.getNextSibling()!!.delete() ++ } ++ newElement = bodyNode!!.getPsi()!!.replace(JetPsiFactory.createFunctionBody(element.getProject(), bodyNode.getText())) ++ ++ //handles the case of the block statement being on a new line ++ if (newElement?.getPrevSibling()?.getText() != "")"") {","Checking for `is PsiWhiteSpace` is more robust. +",2014-03-04 16:06:11 +130,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import com.intellij.lang.ASTNode ++import com.intellij.psi.PsiElement ++import com.siyeh.ig.PsiReplacementUtil ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5 ++ if (caretLocation < elseLocation) { ++ expressionType = ""if"" ++ } ++ } ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ if (jetBlockElement != null) return false ++ ++ setText(""Add braces to '$expressionType' statement"") ++ return true ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val bodyNode = when (expressionType) { ++ ""else"" -> element.getNode().findChildByType(JetNodeTypes.ELSE) ++ ""if"" -> element.getNode().findChildByType(JetNodeTypes.THEN) ++ else -> element.getNode().findChildByType(JetNodeTypes.BODY) ++ } ++ generateCleanOutput(element, bodyNode) ++ } ++ ++ fun generateCleanOutput(element: JetExpressionImpl, bodyNode: ASTNode?) { ++ val newElement: PsiElement? ++ ++ if (element.getNextSibling()?.getText() == "";"") { ++ element.getNextSibling()!!.delete() ++ } ++ newElement = bodyNode!!.getPsi()!!.replace(JetPsiFactory.createFunctionBody(element.getProject(), bodyNode.getText())) ++ ++ //handles the case of the block statement being on a new line ++ if (newElement?.getPrevSibling()?.getText() != "")"") { ++ newElement!!.getPrevSibling()!!.replace(JetPsiFactory.createWhiteSpace(element.getProject())) ++ } ++ //handles the case of no space between condition and statement ++ if (newElement?.getPrevSibling()?.getText() == "")"") {","Shouldn't it be just an `else` for previous `if`? +",2014-03-04 16:06:22 +131,"@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import com.intellij.lang.ASTNode ++import com.intellij.psi.PsiElement ++import com.siyeh.ig.PsiReplacementUtil ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++public class AddBracesIntention : JetSelfTargetingIntention(""add.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5 ++ if (caretLocation < elseLocation) { ++ expressionType = ""if"" ++ } ++ } ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ if (jetBlockElement != null) return false ++ ++ setText(""Add braces to '$expressionType' statement"") ++ return true ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val bodyNode = when (expressionType) { ++ ""else"" -> element.getNode().findChildByType(JetNodeTypes.ELSE) ++ ""if"" -> element.getNode().findChildByType(JetNodeTypes.THEN) ++ else -> element.getNode().findChildByType(JetNodeTypes.BODY) ++ } ++ generateCleanOutput(element, bodyNode) ++ } ++ ++ fun generateCleanOutput(element: JetExpressionImpl, bodyNode: ASTNode?) { ++ val newElement: PsiElement? ++ ++ if (element.getNextSibling()?.getText() == "";"") { ++ element.getNextSibling()!!.delete() ++ } ++ newElement = bodyNode!!.getPsi()!!.replace(JetPsiFactory.createFunctionBody(element.getProject(), bodyNode.getText())) ++ ++ //handles the case of the block statement being on a new line ++ if (newElement?.getPrevSibling()?.getText() != "")"") { ++ newElement!!.getPrevSibling()!!.replace(JetPsiFactory.createWhiteSpace(element.getProject())) ++ } ++ //handles the case of no space between condition and statement ++ if (newElement?.getPrevSibling()?.getText() == "")"") { ++ newElement!!.addBefore(JetPsiFactory.createWhiteSpace(element.getProject()), newElement.getFirstChild()) ++ } ++ if (expressionType == ""do...while"") { ++ newElement?.getNextSibling()?.delete() ++ } ++ bodyNode.getPsi()!!.delete()","What is this for? Couldn't understand without comment. +",2014-03-04 16:06:31 +137,"@@ -0,0 +1,94 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++//import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.JetNodeTypes ++import com.intellij.psi.PsiComment ++import com.intellij.psi.PsiElement ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++//import org.jetbrains.jet.lang.psi.psiUtil.getExpressionKind","Commented imports? Are you sure? :) +",2014-03-05 16:43:00 +205,"@@ -0,0 +1,95 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false","Yes, our formatter fails here at the moment, but you still should indent this line manually with 4 spaces +",2014-04-22 23:48:59 +202,"@@ -0,0 +1,95 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ return hasExplicitReturnType(element) || hasExplicitReceiverType(element) || hasExplicitParamType(element) ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ if (oldParameterList?.getParameters() != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameterList!!.getParameters().map({parameter -> parameter.getNameIdentifier()!!.getText()!! ++ }).makeString("", "", ""("", "")"")","Formatting got screwed up while you were modifying this code. It should be: + +``` +val ....map({ + parameter -> ... +}).makeString(...) +``` +",2014-04-22 23:43:55 +204,"@@ -0,0 +1,95 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ return hasExplicitReturnType(element) || hasExplicitReceiverType(element) || hasExplicitParamType(element) ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ if (oldParameterList?.getParameters() != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameterList!!.getParameters().map({parameter -> parameter.getNameIdentifier()!!.getText()!! ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ oldParameterList.replace(newParameterList) ++ } ++ ++ if (!hasExplicitParamType(element)) { ++ val currentParamList = element.getFunctionLiteral().getValueParameterList() ++ val firstChild = currentParamList?.getFirstChild() ++ if (firstChild?.getNode()?.getElementType() == JetTokens.LPAR) firstChild!!.delete() ++ val lastChild = currentParamList?.getLastChild() ++ if (lastChild?.getNode()?.getElementType() == JetTokens.RPAR) lastChild!!.delete() ++ } ++ } ++ ++ private fun hasExplicitReturnType(element: JetFunctionLiteralExpression): Boolean { ++ return element.hasDeclaredReturnType() ++ } ++ ++ private fun hasExplicitReceiverType(element: JetFunctionLiteralExpression): Boolean { ++ return element.getFunctionLiteral().getReceiverTypeRef() != null ++ } ++ ++ private fun hasExplicitParamType(element: JetFunctionLiteralExpression): Boolean { ++ val parameters = element.getFunctionLiteral().getValueParameterList()?.getParameters() ++ if (parameters == null) return false ++ var numExplicitParams = 0","Better, but shouldn't it be a boolean `hasExplicitParamType`? :) +",2014-04-22 23:45:57 +203,"@@ -0,0 +1,95 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetParameter ++import org.jetbrains.jet.lexer.JetTokens ++ ++public class MakeTypeImplicitInLambdaIntention : JetSelfTargetingIntention( ++ ""make.type.implicit.in.lambda"", javaClass()) { ++ override fun isApplicableTo(element: JetFunctionLiteralExpression): Boolean { ++ throw IllegalStateException(""isApplicableTo(JetExpressionImpl, Editor) should be called instead"") ++ } ++ ++ override fun isApplicableTo(element: JetFunctionLiteralExpression, editor: Editor): Boolean { ++ val openBraceOffset = element.getLeftCurlyBrace().getStartOffset() ++ val closeBraceOffset = element.getRightCurlyBrace()?.getStartOffset() ++ val caretLocation = editor.getCaretModel().getOffset() ++ val arrow = element.getFunctionLiteral().getArrowNode() ++ if (arrow != null && !(openBraceOffset < caretLocation && caretLocation < arrow.getStartOffset() + 2) && ++ caretLocation != closeBraceOffset) return false ++ else if (arrow == null && caretLocation != openBraceOffset + 1 && caretLocation != closeBraceOffset) return false ++ return hasExplicitReturnType(element) || hasExplicitReceiverType(element) || hasExplicitParamType(element) ++ } ++ ++ override fun applyTo(element: JetFunctionLiteralExpression, editor: Editor) { ++ val functionLiteral = element.getFunctionLiteral() ++ val oldParameterList = functionLiteral.getValueParameterList() ++ ++ if (hasExplicitReturnType(element)) { ++ val childAfterParamList = oldParameterList?.getNextSibling() ++ val arrow = functionLiteral.getArrowNode()?.getPsi() ++ val childBeforeArrow = arrow?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterParamList, childBeforeArrow) ++ val whiteSpaceBeforeArrow = JetPsiFactory.createWhiteSpace(element.getProject()) ++ functionLiteral.addBefore(whiteSpaceBeforeArrow, arrow) ++ } ++ ++ if (hasExplicitReceiverType(element)) { ++ val childAfterBrace = functionLiteral.getOpenBraceNode().getPsi()?.getNextSibling() ++ val childBeforeParamList = oldParameterList?.getPrevSibling() ++ functionLiteral.deleteChildRange(childAfterBrace, childBeforeParamList) ++ } ++ ++ if (oldParameterList?.getParameters() != null && hasExplicitParamType(element)) { ++ val parameterString = oldParameterList!!.getParameters().map({parameter -> parameter.getNameIdentifier()!!.getText()!! ++ }).makeString("", "", ""("", "")"") ++ val newParameterList = JetPsiFactory.createParameterList(element.getProject(), parameterString) ++ oldParameterList.replace(newParameterList) ++ } ++ ++ if (!hasExplicitParamType(element)) { ++ val currentParamList = element.getFunctionLiteral().getValueParameterList() ++ val firstChild = currentParamList?.getFirstChild() ++ if (firstChild?.getNode()?.getElementType() == JetTokens.LPAR) firstChild!!.delete() ++ val lastChild = currentParamList?.getLastChild() ++ if (lastChild?.getNode()?.getElementType() == JetTokens.RPAR) lastChild!!.delete() ++ } ++ } ++ ++ private fun hasExplicitReturnType(element: JetFunctionLiteralExpression): Boolean { ++ return element.hasDeclaredReturnType() ++ } ++ ++ private fun hasExplicitReceiverType(element: JetFunctionLiteralExpression): Boolean { ++ return element.getFunctionLiteral().getReceiverTypeRef() != null ++ } ++ ++ private fun hasExplicitParamType(element: JetFunctionLiteralExpression): Boolean { ++ val parameters = element.getFunctionLiteral().getValueParameterList()?.getParameters() ++ if (parameters == null) return false ++ var numExplicitParams = 0 ++ for (param in parameters!!) {","`!!` shouldn't be needed here +",2014-04-22 23:44:54 +579,"@@ -0,0 +1,96 @@ ++/* ++ * Copyright 2010-2016 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.kotlin.idea.quickfix ++ ++import com.intellij.openapi.editor.Editor ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++import org.jetbrains.kotlin.builtins.KotlinBuiltIns ++import org.jetbrains.kotlin.codegen.ExpressionCodegen ++import org.jetbrains.kotlin.idea.caches.resolve.analyze ++import org.jetbrains.kotlin.idea.core.replaced ++import org.jetbrains.kotlin.psi.KtConstantExpression ++import org.jetbrains.kotlin.psi.KtExpression ++import org.jetbrains.kotlin.psi.KtFile ++import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.psiUtil.endOffset ++import org.jetbrains.kotlin.resolve.DescriptorUtils ++import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode ++import org.jetbrains.kotlin.types.KotlinType ++ ++private val valueRanges = mapOf( ++ KotlinBuiltIns.FQ_NAMES._byte to Byte.MIN_VALUE.toLong()..Byte.MAX_VALUE.toLong(), ++ KotlinBuiltIns.FQ_NAMES._short to Short.MIN_VALUE.toLong()..Short.MAX_VALUE.toLong(), ++ KotlinBuiltIns.FQ_NAMES._int to Int.MIN_VALUE.toLong()..Int.MAX_VALUE.toLong(), ++ KotlinBuiltIns.FQ_NAMES._long to Long.MIN_VALUE..Long.MAX_VALUE ++) ++ ++class WrongPrimitiveLiteralFix(element: KtConstantExpression, type: KotlinType) : KotlinQuickFixAction(element) { ++ ++ private val typeName = DescriptorUtils.getFqName(type.constructor.declarationDescriptor!!) ++ private val expectedTypeIsFloat = KotlinBuiltIns.isFloat(type) ++ private val expectedTypeIsDouble = KotlinBuiltIns.isDouble(type) ++ private val constValue ++ = ExpressionCodegen.getPrimitiveOrStringCompileTimeConstant(element, element.analyze(BodyResolveMode.PARTIAL))?.value as? Number ++ ++ private val fixedExpression = buildString { ++ if (expectedTypeIsFloat || expectedTypeIsDouble) { ++ append(constValue) ++ if (expectedTypeIsFloat) { ++ append('F') ++ } ++ else if ('.' !in this) { ++ append("".0"") ++ } ++ } ++ else { ++ if (constValue is Float || constValue is Double) { ++ append(constValue.toLong()) ++ } ++ else { ++ append(element.text.takeWhile { it != 'l' && it != 'L' })","I'd rather use `element.text.trimEnd('l', 'L')` +",2016-07-05 11:03:44 +246,"@@ -0,0 +1,96 @@ ++fun Int.foo(a: Int = 1,","The correct spelling is `extension` :) +",2014-08-20 07:36:15 +132,"@@ -0,0 +1,98 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import com.intellij.psi.PsiComment ++import com.intellij.psi.PsiElement ++import java.util.ArrayList ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++ ++public class RemoveBracesIntention : JetSelfTargetingIntention(""remove.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5 ++ if (caretLocation < elseLocation) { ++ expressionType = ""if"" ++ } ++ } ++ ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ if (jetBlockElement == null) return false ++ ++ if (jetBlockElement!!.getStatements().size == 1) { ++ setText(""Remove braces from '$expressionType' statement"") ++ return true ++ } ++ return false ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ val firstStatement = jetBlockElement!!.getStatements().first() ++ ++ val comments = handleComment(jetBlockElement) ++ if (comments != null) { ++ //TODO - output comments on the line above the control statement ++ } ++ val newElement = jetBlockElement.replace(JetPsiFactory.createExpression(element.getProject(), firstStatement.getText())) ++ ++ if (expressionType == ""do...while"") { ++ newElement.getParent()!!.addAfter(JetPsiFactory.createNewLine(element.getProject()), newElement) ++ } ++ } ++ ++ fun handleComment(element: JetBlockExpression): ArrayList? {","With this function name, it's hard to guess what it does and what does it return. What about ""extractComments""? +It return `ArrayList`, while just `List` would be enough. +",2014-03-04 16:07:09 +133,"@@ -0,0 +1,98 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import com.intellij.psi.PsiComment ++import com.intellij.psi.PsiElement ++import java.util.ArrayList ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++ ++public class RemoveBracesIntention : JetSelfTargetingIntention(""remove.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5 ++ if (caretLocation < elseLocation) { ++ expressionType = ""if"" ++ } ++ } ++ ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ if (jetBlockElement == null) return false ++ ++ if (jetBlockElement!!.getStatements().size == 1) { ++ setText(""Remove braces from '$expressionType' statement"") ++ return true ++ } ++ return false ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ val firstStatement = jetBlockElement!!.getStatements().first() ++ ++ val comments = handleComment(jetBlockElement) ++ if (comments != null) { ++ //TODO - output comments on the line above the control statement ++ } ++ val newElement = jetBlockElement.replace(JetPsiFactory.createExpression(element.getProject(), firstStatement.getText())) ++ ++ if (expressionType == ""do...while"") { ++ newElement.getParent()!!.addAfter(JetPsiFactory.createNewLine(element.getProject()), newElement) ++ } ++ } ++ ++ fun handleComment(element: JetBlockExpression): ArrayList? { ++ val comments = ArrayList() ++ var sibling = element.getFirstChild() ++ if (sibling == null) return null ++ sibling = sibling?.getNextSibling()","This indent blows minds. I thought that this assignment relates to if. +Why safe call here? `sibling` is not null before assignment here. +",2014-03-04 16:07:44 +134,"@@ -0,0 +1,98 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetBlockExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.psiUtil.findBlockInExpression ++import org.jetbrains.jet.JetNodeTypes ++import org.jetbrains.jet.lang.psi.psiUtil.getExpressionType ++import com.intellij.psi.PsiComment ++import com.intellij.psi.PsiElement ++import java.util.ArrayList ++import com.intellij.openapi.fileEditor.FileEditorManager ++import com.intellij.openapi.project.Project ++import com.intellij.psi.PsiFile ++ ++ ++public class RemoveBracesIntention : JetSelfTargetingIntention(""remove.braces"", javaClass()) { ++ private var expressionType: String? = """" ++ private var caretLocation: Int = 1 ++ ++ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { ++ caretLocation = editor.getCaretModel().getOffset() ++ return getTarget(editor, file) != null ++ } ++ ++ override fun isApplicableTo(element: JetExpressionImpl): Boolean { ++ expressionType = element.getExpressionType(element) ++ if (expressionType == null) return false ++ ++ if (expressionType == ""else"") { ++ val elseLocation = (element as JetIfExpression).getElse()!!.getParent()!!.getTextOffset() - 5 ++ if (caretLocation < elseLocation) { ++ expressionType = ""if"" ++ } ++ } ++ ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ if (jetBlockElement == null) return false ++ ++ if (jetBlockElement!!.getStatements().size == 1) { ++ setText(""Remove braces from '$expressionType' statement"") ++ return true ++ } ++ return false ++ } ++ ++ override fun applyTo(element: JetExpressionImpl, editor: Editor) { ++ val jetBlockElement = element.findBlockInExpression(element, expressionType) ++ val firstStatement = jetBlockElement!!.getStatements().first() ++ ++ val comments = handleComment(jetBlockElement) ++ if (comments != null) { ++ //TODO - output comments on the line above the control statement ++ } ++ val newElement = jetBlockElement.replace(JetPsiFactory.createExpression(element.getProject(), firstStatement.getText())) ++ ++ if (expressionType == ""do...while"") { ++ newElement.getParent()!!.addAfter(JetPsiFactory.createNewLine(element.getProject()), newElement) ++ } ++ } ++ ++ fun handleComment(element: JetBlockExpression): ArrayList? { ++ val comments = ArrayList() ++ var sibling = element.getFirstChild() ++ if (sibling == null) return null ++ sibling = sibling?.getNextSibling() ++ ++ while (sibling != null) { ++ if (sibling is PsiComment) { ++ comments.add(sibling as PsiComment) ++ } ++ sibling = sibling?.getNextSibling()","Another redundant safe call. +",2014-03-04 16:08:03 +243,"@@ -0,0 +1,98 @@ ++class A(val a: Int = 1, ++ val b: Int = 2, ++ val c: Int = 3, ++ val d: Int = 4, ++ val e: Int = 5, ++ val f: Int = 6, ++ val g: Int = 7, ++ val h: Int = 8, ++ val i: Int = 9, ++ val j: Int = 10, ++ val k: Int = 11, ++ val l: Int = 12, ++ val m: Int = 13, ++ val n: Int = 14, ++ val o: Int = 15, ++ val p: Int = 16, ++ val q: Int = 17, ++ val r: Int = 18, ++ val s: Int = 19, ++ val t: Int = 20, ++ val u: Int = 21, ++ val v: Int = 22, ++ val w: Int = 23, ++ val x: Int = 24, ++ val y: Int = 25, ++ val z: Int = 26, ++ val aa: Int = 27, ++ val bb: Int = 28, ++ val cc: Int = 29, ++ val dd: Int = 30, ++ val ee: Int = 31, ++ val ff: Int = 32, ++ val gg: Int = 33, ++ val hh: Int = 34, ++ val ii: Int = 35, ++ val jj: Int = 36, ++ val kk: Int = 37, ++ val ll: Int = 38, ++ val mm: Int = 39, ++ val nn: Int = 40, ++ val oo: Int = 41, ++ val pp: Int = 42, ++ val qq: Int = 43, ++ val rr: Int = 44, ++ val ss: Int = 45, ++ val tt: Int = 46, ++ val uu: Int = 47, ++ val vv: Int = 48, ++ val ww: Int = 49, ++ val xx: Int = 50, ++ val yy: Int = 51, ++ val zz: Int = 52, ++ val aaa: Int = 53, ++ val bbb: Int = 54, ++ val ccc: Int = 55, ++ val ddd: Int = 56, ++ val eee: Int = 57, ++ val fff: Int = 58, ++ val ggg: Int = 59, ++ val hhh: Int = 60, ++ val iii: Int = 61, ++ val jjj: Int = 62, ++ val kkk: Int = 63, ++ val lll: Int = 64, ++ val mmm: Int = 65, ++ val nnn: Int = 66, ++ val ooo: Int = 67, ++ val ppp: Int = 68, ++ val qqq: Int = 69, ++ val rrr: Int = 70) { ++ override fun toString(): String { ++ return ""$a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z $aa $bb $cc $dd $ee $ff $gg $hh $ii $jj $kk "" + ++ ""$ll $mm $nn $oo $pp $qq $rr $ss $tt $uu $vv $ww $xx $yy $zz $aaa $bbb $ccc $ddd $eee $fff $ggg $hhh $iii $jjj $kkk $lll "" + ++ ""$mmm $nnn $ooo $ppp $qqq $rrr"" ++ } ++} ++ ++fun box(): String { ++ val test1 = A(5, f = 3, w = 1, aa = 71, nn = 2, qq = 15, ww = 97, aaa = 261258, iii = 3, nnn = 8, rrr = 7).toString() ++ val test2 = A().toString() ++ val test3 = A(70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, ++ 40, 39, 38, 37, 36, jj = 35, kk = 34, ll = 33, mm = 32, nn = 31, oo = 30, pp = 29, qq = 28, rr = 27, ss = 26, tt = 25, ++ uu = 24, vv = 23, ww = 22, xx = 21, yy = 20, zz = 19, aaa = 18, bbb = 17, ccc = 16, ddd = 15, eee = 14, fff = 13, ++ ggg = 12, hhh = 11, iii = 10, jjj = 9, kkk = 8, lll = 7, mmm = 6, nnn = 5, ooo = 4, ppp = 3, qqq = 2, rrr = 1).toString() ++ if (test1 != ""5 2 3 4 5 3 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 1 24 25 26 71 28 29 30 31 32 33 34 35 36 37 38 39 2 41 42 15 "" + ++ ""44 45 46 47 48 97 50 51 52 261258 54 55 56 57 58 59 60 3 62 63 64 65 8 67 68 69 7"") { ++ return test1 ++ } ++ if (test2 != ""1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 "" + ++ ""43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70"") { ++ return test2 ++ } ++ if (test3 != ""70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 "" + ++ ""31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1"") { ++ return test3 ++ } ++ return ""OK""","Unfortunately no test checks the introduced behavior in `FunctionCodegen#generateConstructorWithoutParametersIfNeeded()`. + +This test looks almost as if it does, but `A()` here is only a syntactic sugar for invoking the `$default` method :) + +To test precisely the synthetic no-args constructor we generate for a class whose constructor's arguments are all default, you could either invoke it from Java or call it reflectively via `newInstance` (I recommend the latter). +",2014-08-20 07:27:47 +107,"@@ -0,0 +1,99 @@ ++/* ++ * Copyright 2010-2014 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.intentions ++ ++import com.intellij.openapi.editor.Editor ++import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression ++import org.jetbrains.jet.lang.psi.JetCallExpression ++import org.jetbrains.jet.lang.psi.JetExpression ++import org.jetbrains.jet.lang.psi.JetPsiFactory ++import org.jetbrains.jet.lang.psi.JetValueArgument ++import org.jetbrains.jet.lang.psi.JetValueArgumentList ++import org.jetbrains.jet.lang.psi.JetNamedArgumentImpl ++import org.jetbrains.jet.lang.psi.JetValueArgumentName ++import org.jetbrains.jet.plugin.references.JetSimpleNameReference ++import org.jetbrains.jet.lang.psi.JetBinaryExpression ++import org.jetbrains.jet.lang.psi.JetPostfixExpression ++import org.jetbrains.jet.lang.psi.JetTypeArgumentList ++ ++public class ReplaceGetCallWithArrayAccessIntention : JetSelfTargetingIntention(""replace.get.call.with.array.access"", javaClass()) { ++ override fun isApplicableTo(element: JetExpression): Boolean { ++ fun methodCallCheck(expression: JetDotQualifiedExpression): Boolean { ++ val selector = expression.getSelectorExpression() ++ val receiver = expression.getReceiverExpression() ++ ++ if (selector is JetCallExpression && !(receiver is JetPostfixExpression)) { ++ val callee = selector.getCalleeExpression() ++ val arguments = selector.getValueArgumentList() ++ val typeArguments = selector.getTypeArgumentList() ++ ++ return arguments != null ++ && typeArguments == null ++ && !arguments.getArguments().any { (arg): Boolean -> arg.getArgumentName() != null }","Specifying return type in function literal is redundant here. Explicit parameter can be also omitted (""it"" name will be auto-generated for it). +",2014-02-07 18:33:54 +956,"@@ -0,0 +1,99 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression ++ ++class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (!function.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return ++ ++ val bodyExpression = function.bodyExpression ++ bodyExpression ?: return ++ ++ val body = if (bodyExpression is KtDotQualifiedExpression) { ++ bodyExpression ++ } ++ else { ++ if (bodyExpression.children.size != 1) { ++ return ++ } ++ bodyExpression.children[0]",You could use `singleOrNull() ?: return` here.,2017-08-14 09:14:30 +957,"@@ -0,0 +1,99 @@ ++/* ++ * Copyright 2010-2017 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.kotlin.idea.inspections ++ ++import com.intellij.codeInspection.* ++import com.intellij.openapi.project.Project ++import org.jetbrains.kotlin.lexer.KtTokens ++import org.jetbrains.kotlin.psi.* ++import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression ++ ++class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { ++ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = ++ object : KtVisitorVoid() { ++ override fun visitNamedFunction(function: KtNamedFunction) { ++ super.visitNamedFunction(function) ++ if (!function.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return ++ ++ val bodyExpression = function.bodyExpression ++ bodyExpression ?: return ++ ++ val body = if (bodyExpression is KtDotQualifiedExpression) { ++ bodyExpression ++ } ++ else { ++ if (bodyExpression.children.size != 1) { ++ return ++ } ++ bodyExpression.children[0] ++ } ++ ++ val qualifiedExpression = if (body is KtReturnExpression) { ++ val returnedExpression = body.returnedExpression ++ returnedExpression ?: return ++ returnedExpression as? KtDotQualifiedExpression ?: return ++ } ++ else { ++ body as? KtDotQualifiedExpression ?: return ++ } ++ ++ if (qualifiedExpression.receiverExpression !is KtSuperExpression) return ++ ++ val superSelectorExpression = qualifiedExpression.selectorExpression ++ val superCallElement = superSelectorExpression as? KtCallElement ?: return ++ ++ if (!isSameFunctionName(superSelectorExpression, function)) return",I can use `superCallElement` for the argument. I will fix it.,2017-08-14 10:21:40 +95,"@@ -1,11 +1,11 @@ + + + +- ++ ","Changes like this in meta-information should be carefully reviewed before committing, because they can easily break compilation or workflow for other developers. +",2014-01-27 21:23:50 +312,"@@ -1,15 +1,15 @@ + package kotlin + + /** +- * Creates a tuple of type [[Pair]] from this and *that* which can be useful for creating [[Map]] literals +- * with less noise, for example +- +- * @includeFunctionBody ../../test/collections/MapTest.kt createUsingTo ++ * Creates a tuple of type [Pair] from this and [that]. ++ * ++ * This can be useful for creating [Map] literals with less noise, for example: ++ * @sample test.collections.MapTest.createUsingTo + */ + public fun A.to(that: B): Pair = Pair(this, that) + + /** +-Run function f ++ * Runs the specified function.","Runs -> Calls? +",2015-02-09 16:24:56 +543,"@@ -1,3 +1,19 @@ ++/*","It's added by IDEA's pre-commit action. Really shouldn't for generated files. +",2016-04-25 23:33:19 +767,"@@ -1,3 +1,3 @@ + package test + +-fun lll(a: Int) = a ++fun lll(a: kotlin.Int) = a",Here we have `kotlin.` added too,2017-04-19 15:42:08 +768,"@@ -1,4 +1,4 @@ + package test + + // extra parameter is to make sure generic signature is not erased +-fun doNothing(array: IntArray, ignore: java.util.List) = array ++fun doNothing(array: kotlin.IntArray, ignore: java.util.List) = array",And here we have `kotlin.` too,2017-04-19 15:42:26 +726,"@@ -1,4 +1,4 @@ + package test + + // extra parameter is to preserve generic signature +-fun anyany(a: Any, ignore: java.util.List) = a ++fun anyany(a: kotlin.Any, ignore: java.util.List) = a",Unclear. Why should you have `kotlin.` here and how it works without it?,2017-04-05 15:28:43 +984,"@@ -1,4 +1,5 @@ + package org.junit + ++@Deprecated(""Use 'Test' from kotlin.test package"", replaceWith = ReplaceWith(""Test"", imports = ""kotlin.test.Test""))",👍 ,2017-08-15 16:51:33 +207,"@@ -1,6 +1,10 @@ + // ""Change 'foo' function return type to '([ERROR : NoSuchType]) -> Int'"" ""false"" ++// ACTION: Disable 'Make Types Implicit In Lambda' ++// ACTION: Edit intention settings ++// ACTION: Make types implicit in lambda","Note that this test is now failing again due to obvious reasons :) +",2014-04-23 12:29:36 +646,"@@ -1,7 +1,6 @@ + fun foo() { +- val a: kotlin.test.Asserter? +- if () { +- a = null ++ val a = if () {","It's not OK that you're losing the variable type here. +",2016-10-18 18:59:07 +381,"@@ -1,72 +0,0 @@ +-/* +- * Copyright 2010-2015 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.kotlin.idea.quickfix +- +-import org.jetbrains.kotlin.psi.* +-import kotlin.platform.* +-import org.jetbrains.kotlin.diagnostics.* +-import com.intellij.codeInsight.intention.* +-import org.jetbrains.kotlin.idea.* +-import com.intellij.openapi.project.* +-import com.intellij.openapi.editor.* +-import com.intellij.psi.* +-import org.jetbrains.kotlin.idea.project.PluginJetFilesProvider +-import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionFactory +-import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType +-import org.jetbrains.kotlin.lexer.JetTokens +-import org.jetbrains.kotlin.psi.psiUtil.* +-import java.util.ArrayList +- +- +-public class AddInitKeywordFix(element: JetClassInitializer) : JetIntentionAction(element) { +- override fun getText() = JetBundle.message(""add.init.keyword"") +- +- override fun getFamilyName() = JetBundle.message(""add.init.keyword.family"") +- +- override fun invoke(project: Project, editor: Editor?, file: JetFile) { +- addInitKeyword(element) +- } +- +- companion object Factory : JetSingleIntentionActionFactory() { +- override fun createAction(diagnostic: Diagnostic) = diagnostic.createIntentionForFirstParentOfType(::AddInitKeywordFix) +- +- public fun createWholeProjectFixFactory(): JetSingleIntentionActionFactory = createIntentionFactory { +- JetWholeProjectForEachElementOfTypeFix.createByPredicate( +- predicate = { !it.hasInitKeyword() }, +- taskProcessor = { addInitKeyword(it) }, +- modalTitle = JetBundle.message(""add.init.keyword.in.whole.project.modal.title""), +- name = JetBundle.message(""add.init.keyword.in.whole.project""), +- familyName = JetBundle.message(""add.init.keyword.in.whole.project.family"") +- ) +- } +- +- private fun addInitKeyword(element: JetClassInitializer) { +- if (element.hasInitKeyword()) return +- +- val psiFactory = JetPsiFactory(element) +- val initKeyword = psiFactory.createInitKeyword()","JetPsiFactory.createInitKeyword became unused +",2015-04-29 11:30:03 +635,"@@ -1,8 +1,9 @@ + object A { + @JvmStatic fun main(args: Array) { +- println(Void.TYPE) +- println(Integer.TYPE) +- println(java.lang.Double.TYPE) ++ println(Unit::class.javaPrimitiveType)","This doesn't actually work: `Unit` has no `javaPrimitiveType`. For `void.class`, the previous variant of the code should be used. +",2016-10-10 17:23:18 +311,"@@ -10,21 +10,34 @@ import kotlin.jvm.internal.Intrinsic + * + * Example: + * +- * throws(javaClass()) +- * fun readFile(name: String): String {...} ++ * ``` ++ * throws(javaClass()) ++ * fun readFile(name: String): String {...} ++ * ``` + * + * will be translated to + * +- * String readFile(String name) throws IOException {...} ++ * ``` ++ * String readFile(String name) throws IOException {...} ++ * ``` + */ + Retention(RetentionPolicy.SOURCE) + public annotation class throws(public vararg val exceptionClasses: Class) + ++/** ++ * Returns the runtime Java class of this object. ++ */ + [Intrinsic(""kotlin.javaClass.property"")] public val T.javaClass : Class + get() = (this as java.lang.Object).getClass() as Class + ++/** ++ * Returns the Java class for the specified type. ++ */ + [Intrinsic(""kotlin.javaClass.function"")] public fun javaClass(): Class = null as Class + ++/** ++ * Executes the given function [block] while holding the monitor of the given object [lock].","Somewhere I saw you called it ""semaphore"", and here calling ""monitor"" +",2015-02-09 16:23:16 +954,"@@ -10,6 +10,12 @@ class BasicAssertionsTest { + } + + @Test ++ fun testAssertSame() {","`test` prefix reminds me old days of `JUnit`, where it was obligatory to run any test :-) + +Could you tell me why there is doubled `kotlin` and `test` packages in path: `kotlin/libraries/kotlin.test/common/src/test/kotlin/kotlin/test/tests/`? Just wondering.",2017-08-08 06:08:19 +589,"@@ -10,6 +10,12 @@ package kotlin.text + public inline fun buildString(builderAction: StringBuilder.() -> Unit): String = StringBuilder().apply(builderAction).toString() + + /** ++ * Builds new string by populating newly created [StringBuilder] initialized with the given capacity using provided [builderAction] and then converting it to [String]. ++ */","Will fix formatting upon rebase. +",2016-08-08 22:59:18 +557,"@@ -10,6 +10,12 @@ package kotlin.text + public inline fun buildString(builderAction: StringBuilder.() -> Unit): String = StringBuilder().apply(builderAction).toString() + + /** ++ * Builds new string by populating newly created [StringBuilder] initialized with the given capacity using provided [builderAction] and then converting it to [String]. ++ */ ++@kotlin.internal.InlineOnly ++inline fun buildString(length : Int, builderAction: StringBuilder.() -> Unit): String = StringBuilder(length).apply(builderAction).toString()","Constructor parameter is called `capacity` so it should have the same name here. +Also there should be no space before `:` in parameter definition. +",2016-05-17 17:43:41 +293,"@@ -10,9 +10,9 @@ import java.util.* + import java.util.Collections // TODO: it's temporary while we have java.util.Collections in js + + /** +- * Appends the string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied +- * If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will +- * a special *truncated* separator (which defaults to ""..."") ++ * Appends the string from all the elements separated using [separator] and using the given [prefix] and *postfix* if supplied.","Linkify `postfix` +",2015-02-09 15:54:25 +294,"@@ -10,9 +10,9 @@ import java.util.* + import java.util.Collections // TODO: it's temporary while we have java.util.Collections in js + + /** +- * Appends the string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied +- * If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will +- * a special *truncated* separator (which defaults to ""..."") ++ * Appends the string from all the elements separated using [separator] and using the given [prefix] and *postfix* if supplied. ++ * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] ++ * elements will be appended, followed by the [truncated] string (which defaults to ""..."").","Ideally `trucated` should default to ""…"", not ""..."" +",2015-02-09 15:55:06 +332,"@@ -100,65 +181,143 @@ public class Byte private () : Number, Comparable { + * On the JVM, non-nullable values of this type are represented as values of the primitive type `char`. + */ + public class Char private () : Comparable { +- class object {} ++ default object {} + ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Byte): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public override fun compareTo(other: Char): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Short): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Int): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Long): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Float): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Double): Int + ++ /** Adds the two values. */ + public fun plus(other: Byte): Int ++ /** Adds the two values. */ + public fun plus(other: Short): Int ++ /** Adds the two values. */ + public fun plus(other: Int): Int ++ /** Adds the two values. */ + public fun plus(other: Long): Long ++ /** Adds the two values. */ + public fun plus(other: Float): Float ++ /** Adds the two values. */ + public fun plus(other: Double): Double + ++ /** Subtracts the other value from this value. */ + public fun minus(other: Byte): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Char): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Short): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Int): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Long): Long ++ /** Subtracts the other value from this value. */ + public fun minus(other: Float): Float ++ /** Subtracts the other value from this value. */ + public fun minus(other: Double): Double + ++ /** Multiplies the two values. */ + public fun times(other: Byte): Int ++ /** Multiplies the two values. */ + public fun times(other: Short): Int ++ /** Multiplies the two values. */ + public fun times(other: Int): Int ++ /** Multiplies the two values. */ + public fun times(other: Long): Long ++ /** Multiplies the two values. */ + public fun times(other: Float): Float ++ /** Multiplies the two values. */ + public fun times(other: Double): Double + ++ /** Divides this value by the other value. */ + public fun div(other: Byte): Int ++ /** Divides this value by the other value. */ + public fun div(other: Short): Int ++ /** Divides this value by the other value. */ + public fun div(other: Int): Int ++ /** Divides this value by the other value. */ + public fun div(other: Long): Long ++ /** Divides this value by the other value. */ + public fun div(other: Float): Float ++ /** Divides this value by the other value. */ + public fun div(other: Double): Double + ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Byte): Int ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Short): Int ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Int): Int ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Long): Long ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Float): Float ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Double): Double + ++ /** Increments this value. */ + public fun inc(): Char ++ /** Decrements this value. */ + public fun dec(): Char ++ /** Returns this value. */ + public fun plus(): Int ++ /** Returns the negative of this value. */ + public fun minus(): Int + ++ /** Creates a range from this value to the specified [other] value. */ + public fun rangeTo(other: Char): CharRange","We don't have other overloads for rangeTo, like in other types? +",2015-03-12 14:45:44 +333,"@@ -100,65 +181,143 @@ public class Byte private () : Number, Comparable { + * On the JVM, non-nullable values of this type are represented as values of the primitive type `char`. + */ + public class Char private () : Comparable { +- class object {} ++ default object {} + ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Byte): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public override fun compareTo(other: Char): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Short): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Int): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Long): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Float): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Double): Int + ++ /** Adds the two values. */ + public fun plus(other: Byte): Int ++ /** Adds the two values. */ + public fun plus(other: Short): Int ++ /** Adds the two values. */ + public fun plus(other: Int): Int ++ /** Adds the two values. */ + public fun plus(other: Long): Long ++ /** Adds the two values. */ + public fun plus(other: Float): Float ++ /** Adds the two values. */ + public fun plus(other: Double): Double + ++ /** Subtracts the other value from this value. */ + public fun minus(other: Byte): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Char): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Short): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Int): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Long): Long ++ /** Subtracts the other value from this value. */ + public fun minus(other: Float): Float ++ /** Subtracts the other value from this value. */ + public fun minus(other: Double): Double + ++ /** Multiplies the two values. */ + public fun times(other: Byte): Int ++ /** Multiplies the two values. */ + public fun times(other: Short): Int ++ /** Multiplies the two values. */ + public fun times(other: Int): Int ++ /** Multiplies the two values. */ + public fun times(other: Long): Long ++ /** Multiplies the two values. */ + public fun times(other: Float): Float ++ /** Multiplies the two values. */ + public fun times(other: Double): Double + ++ /** Divides this value by the other value. */ + public fun div(other: Byte): Int ++ /** Divides this value by the other value. */ + public fun div(other: Short): Int ++ /** Divides this value by the other value. */ + public fun div(other: Int): Int ++ /** Divides this value by the other value. */ + public fun div(other: Long): Long ++ /** Divides this value by the other value. */ + public fun div(other: Float): Float ++ /** Divides this value by the other value. */ + public fun div(other: Double): Double + ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Byte): Int ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Short): Int ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Int): Int ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Long): Long ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Float): Float ++ /** Calculates the remainder of dividing this value by the other value. */ + public fun mod(other: Double): Double + ++ /** Increments this value. */ + public fun inc(): Char ++ /** Decrements this value. */ + public fun dec(): Char ++ /** Returns this value. */ + public fun plus(): Int ++ /** Returns the negative of this value. */ + public fun minus(): Int + ++ /** Creates a range from this value to the specified [other] value. */ + public fun rangeTo(other: Char): CharRange + ++ /** Returns the value of this character as a `name`. */","As a name? +",2015-03-12 14:46:03 +975,"@@ -105,8 +105,19 @@ public KotlinTypeInfo visitIfExpression(KtIfExpression ifExpression, ExpressionT + + LexicalWritableScope thenScope = newWritableScopeImpl(context, LexicalScopeKind.THEN, components.overloadChecker); + LexicalWritableScope elseScope = newWritableScopeImpl(context, LexicalScopeKind.ELSE, components.overloadChecker); +- DataFlowInfo thenInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo); +- DataFlowInfo elseInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo); ++ DataFlowInfo basicThenInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo); ++ DataFlowInfo thenInfoFromES = components.effectSystem.getConditionalInfoForThenBranch(",I'd expect here some language feature check.,2017-08-15 16:13:17 +385,"@@ -107,29 +106,38 @@ protected ExitCode doExecute( + Project project = environmentForJS.getProject(); + List sourcesFiles = environmentForJS.getSourceFiles(); + +- if (arguments.verbose) { +- reportCompiledSourcesList(messageCollector, sourcesFiles); ++ if (arguments.outputFile == null) { ++ messageSeverityCollector.report(CompilerMessageSeverity.ERROR, ""Specify output file via -output"", CompilerMessageLocation.NO_LOCATION); ++ return ExitCode.INTERNAL_ERROR; + } + +- if (arguments.outputFile == null) { +- messageCollector.report(CompilerMessageSeverity.ERROR, ""Specify output file via -output"", CompilerMessageLocation.NO_LOCATION); ++ if (messageSeverityCollector.anyReported(CompilerMessageSeverity.ERROR)) { + return ExitCode.INTERNAL_ERROR; + } + ++ if (sourcesFiles.isEmpty()) { ++ messageSeverityCollector.report(CompilerMessageSeverity.ERROR, ""No source files"", CompilerMessageLocation.NO_LOCATION); ++ return COMPILATION_ERROR;","Maybe we should have another exit code for such cases? e.g. `ILLEGAL_ARGUMENTS_ERROR`. + +//cc @udalov +",2015-06-11 10:41:44 +694,"@@ -110,7 +149,10 @@ fun createContainerForLazyResolveWithJava( + useImpl() + } + }.apply { +- get().initialize(bindingTrace, get()) ++ if (useJavac) ++ get().initialize(bindingTrace, get())",I'd write here `JavacBasedClassFinder`. The current name is too close to just `JavaClassFinder`.,2017-04-05 12:17:44 +872,"@@ -111,7 +114,9 @@ interface ReplEvalAction { + + sealed class ReplEvalResult : Serializable { + class ValueResult(val value: Any?) : ReplEvalResult() { +- override fun toString(): String = ""Result: $value"" ++ val type = LastInferredTypeHolder.inferredType.get()",I think you can obtain this type from `compileResult` at `GenericReplEvaluator.eval` and pass to `ValueResult`'s constructor here,2017-06-13 14:36:40 +889,"@@ -112,9 +112,18 @@ class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() { + else -> ""Property"" + } + val nameElement = (declaration as? PsiNameIdentifierOwner)?.nameIdentifier ?: return +- holder.registerProblem(declaration.visibilityModifier() ?: nameElement, ++ val visibilityModifier = declaration.visibilityModifier() ++ val fix = object : AddModifierFix(modifierListOwner, KtTokens.PRIVATE_KEYWORD) {","I would do this as a general fix to AddModifierFix (which already has special logic for handling modality modifiers), not as a single-case override here.",2017-07-10 09:10:34 +496,"@@ -112,9 +112,20 @@ void parseFile() { + parseTopLevelDeclaration(); + } + ++ checkUnclosedBlockComment(); + fileMarker.done(KT_FILE); + } + ++ private void checkUnclosedBlockComment() { ++ if (TokenSet.create(BLOCK_COMMENT, DOC_COMMENT).contains(myBuilder.rawLookup(-1))) { ++ int startOffset = myBuilder.rawTokenTypeStart(-1); ++ int endOffset = myBuilder.rawTokenTypeStart(0); ++ if (!myBuilder.getOriginalText().subSequence(startOffset, endOffset).toString().endsWith(""*/"")) {","This may materialize a huge file as a single string (in case of this file being commented entirely) + +We could probably use other means, such as: +- changing the lexer to emit a special token type on unfinished comments +- using the CharSequence API to only materialize the last two characters as String, and not the entire text +",2015-12-17 16:52:41 +497,"@@ -112,9 +112,20 @@ void parseFile() { + parseTopLevelDeclaration(); + } + ++ checkUnclosedBlockComment(); + fileMarker.done(KT_FILE); + } + ++ private void checkUnclosedBlockComment() { ++ if (TokenSet.create(BLOCK_COMMENT, DOC_COMMENT).contains(myBuilder.rawLookup(-1))) { ++ int startOffset = myBuilder.rawTokenTypeStart(-1); ++ int endOffset = myBuilder.rawTokenTypeStart(0); ++ if (!myBuilder.getOriginalText().subSequence(startOffset, endOffset).toString().endsWith(""*/"")) { ++ error(""Unclosed comment"");","This error is placed before the comment, in Java it is at the end of the file +",2015-12-17 16:53:02 +580,"@@ -114,15 +116,28 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { + return null + } + +- private fun renderKotlinDeclaration(declaration: KtDeclaration, quickNavigation: Boolean): String { ++ private fun renderKotlinDeclaration(declaration: KtExpression, quickNavigation: Boolean): String { + val context = declaration.analyze(BodyResolveMode.PARTIAL) +- var declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] ++ val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] + + if (declarationDescriptor == null) { + LOG.info(""Failed to find descriptor for declaration "" + declaration.getElementTextWithContext()) + return ""No documentation available"" + } + ++ return renderKotlin(context, declarationDescriptor, quickNavigation) ++ } ++ ++ private fun renderKotlinImplicitLambdaParameter(element: KtReferenceExpression, quickNavigation: Boolean): String? { ++ val context = element.analyze(BodyResolveMode.PARTIAL) ++ val target = element.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return null ++ context.get(BindingContext.AUTO_CREATED_IT, target)","This line doesn't do anything +",2016-07-05 11:32:13 +581,"@@ -114,15 +116,28 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { + return null + } + +- private fun renderKotlinDeclaration(declaration: KtDeclaration, quickNavigation: Boolean): String { ++ private fun renderKotlinDeclaration(declaration: KtExpression, quickNavigation: Boolean): String { + val context = declaration.analyze(BodyResolveMode.PARTIAL) +- var declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] ++ val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] + + if (declarationDescriptor == null) { + LOG.info(""Failed to find descriptor for declaration "" + declaration.getElementTextWithContext()) + return ""No documentation available"" + } + ++ return renderKotlin(context, declarationDescriptor, quickNavigation) ++ } ++ ++ private fun renderKotlinImplicitLambdaParameter(element: KtReferenceExpression, quickNavigation: Boolean): String? { ++ val context = element.analyze(BodyResolveMode.PARTIAL) ++ val target = element.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return null ++ context.get(BindingContext.AUTO_CREATED_IT, target) ++ return renderKotlin(context, target, quickNavigation) ++ } ++ ++ private fun renderKotlin(context: BindingContext, declarationDescriptor: DeclarationDescriptor, quickNavigation: Boolean): String { ++ @Suppress(""NAME_SHADOWING"") ++ var declarationDescriptor = declarationDescriptor","This doesn't seem to be needed, either +",2016-07-05 11:32:43 +587,"@@ -115,9 +116,73 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() { + } + }) + ++ if (contextElement != null && contextElement !is KtElement) {","Now such variables are skipped during text rendering, so it doesn't matter if they are present in resulting map (this map is used only to get values for kotlin variables that are present in resulting text) +",2016-08-03 14:11:50 +588,"@@ -115,9 +116,73 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() { + } + }) + ++ if (contextElement != null && contextElement !is KtElement) { ++ codeFragment.putCopyableUserData(KtCodeFragment.FAKE_CONTEXT_FOR_JAVA_FILE, { ++ val emptyFile = createFakeFileWithJavaContextElement("""", contextElement) ++ ++ val debuggerContext = DebuggerManagerEx.getInstanceEx(project).context ++ val debuggerSession = debuggerContext.debuggerSession ++ if ((debuggerSession == null || debuggerContext.suspendContext == null) && !ApplicationManager.getApplication().isUnitTestMode) { ++ LOG.warn(""Couldn't create fake context element for java file, debugger isn't paused on breakpoint"") ++ return@putCopyableUserData emptyFile ++ } ++ ++ // TODO: 'this' is unavailable ++ val visibleVariables = getVisibleLocalVariables(contextElement, debuggerContext) ++ if (visibleVariables == null) { ++ LOG.warn(""Couldn't get a list of local variables for ${debuggerContext.sourcePosition.file.name}:${debuggerContext.sourcePosition.line}"") ++ return@putCopyableUserData emptyFile ++ } ++ ++ val fakeFunctionText = ""fun _java_locals_debug_fun_() {\n"" + ++ visibleVariables.entries.associate { it.key.name() to it.value }.kotlinVariablesAsText(project) + ++ ""}"" ++ ++ val fakeFile = createFakeFileWithJavaContextElement(fakeFunctionText, contextElement) ++ val fakeFunction = fakeFile.declarations.firstOrNull() as? KtFunction ++ val fakeContext = (fakeFunction?.bodyExpression as? KtBlockExpression)?.statements?.lastOrNull() ++ ++ return@putCopyableUserData wrapContextIfNeeded(project, contextElement, fakeContext) ?: emptyFile ++ }) ++ } ++ + return codeFragment + } + ++ private fun getVisibleLocalVariables(contextElement: PsiElement?, debuggerContext: DebuggerContextImpl): Map? { ++ val semaphore = Semaphore() ++ semaphore.down() ++ ++ var visibleVariables: Map? = null ++ ++ val worker = object : DebuggerCommandImpl() { ++ override fun action() {","I've replaced it with codeFragment.getContentElement().statements.lastOrNull() to make this line clearer +",2016-08-03 14:13:56 +421,"@@ -116,13 +128,35 @@ private static String execCompiler( + List argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments); + argumentsList.addAll(StringUtil.split(additionalArguments, "" "")); + ++ String[] argsArray = ArrayUtil.toStringArray(argumentsList); ++ ++ // trying the daemon first ++ if (incrementalCaches != null && KotlinCompilerClient.Companion.isDaemonEnabled()) { ++ File libPath = CompilerRunnerUtil.getLibPath(environment.getKotlinPaths(), messageCollector); ++ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ ++ // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler ++ CompilerId compilerId = CompilerId.makeCompilerId(new File(libPath, ""kotlin-compiler.jar"")); ++ DaemonOptions daemonOptions = new DaemonOptions(); ++ DaemonLaunchingOptions daemonLaunchingOptions = new DaemonLaunchingOptions(); ++ KotlinCompilerClient.Companion.configureDaemonLaunchingOptions(daemonLaunchingOptions); ++ // TODO: find proper stream to report daemon connection progress ++ CompileService daemon = KotlinCompilerClient.Companion.connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, System.out, true, true); ++ if (daemon != null) { ++ Integer res = KotlinCompilerClient.Companion.incrementalCompile(daemon, argsArray, incrementalCaches, out); ++ return res.toString(); ++ } ++ } ++ ++ // otherwise fallback to in-process ++ + Object rc = CompilerRunnerUtil.invokeExecMethod( +- compilerClassName, ArrayUtil.toStringArray(argumentsList), environment, messageCollector, out ++ compilerClassName, argsArray, environment, messageCollector, out + ); + + // exec() returns an ExitCode object, class of which is loaded with a different class loader, + // so we take it's contents through reflection + return getReturnCodeFromObject(rc); ++","Extra empty line. +",2015-08-20 14:15:28 +514,"@@ -1162,3 +1162,77 @@ public fun CharSequence.lineSequence(): Sequence = splitToSequence(""\r\n + * * Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ + public fun CharSequence.lines(): List = lineSequence().toList() ++ ++/** ++ * For each i in [0, length), this function computes ++ * the length of the longest suffix of a substring of pattern from 0 to i ++ * that is also a prefix of the pattern itself. ++ */ ++private fun computePrefixFunction(pattern: CharSequence): IntArray { ++ val resultTable = IntArray(pattern.length) ++ ++ var matches = 0 ++ for (i in 1..pattern.length - 1) { ++ while (matches > 0 && pattern[matches] != pattern[i]) { ++ matches = resultTable[matches] ++ } ++ ++ if (pattern[matches] == pattern[i]) { ++ matches++ ++ } ++ resultTable[i] = matches ++ } ++ ++ return resultTable ++} ++ ++/** ++ * Returns a list of indices where the pattern occurs in this String. This method ++ * searches character by character and thus does not support regular expressions ++ * as input for the pattern. ++ * ++ * @param [pattern] The pattern to look for in this String. Regular expressions ++ * are not supported ++ * @param [ignoreCase] If true, characters are matched even if one is upper and the other is ++ * lower case ++ * ++ * @return A list of indices where the supplied [pattern] starts in the text. ++ */ ++public fun CharSequence.occurrencesOf(pattern: CharSequence, ignoreCase: Boolean = false): Sequence { ++ ++ if (isEmpty() || pattern.isEmpty()) {","`if (pattern.isEmpty() || pattern.length > this.length)` ? +",2016-02-16 19:00:19 +515,"@@ -1162,3 +1162,77 @@ public fun CharSequence.lineSequence(): Sequence = splitToSequence(""\r\n + * * Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ + public fun CharSequence.lines(): List = lineSequence().toList() ++ ++/** ++ * For each i in [0, length), this function computes ++ * the length of the longest suffix of a substring of pattern from 0 to i ++ * that is also a prefix of the pattern itself. ++ */ ++private fun computePrefixFunction(pattern: CharSequence): IntArray { ++ val resultTable = IntArray(pattern.length) ++ ++ var matches = 0 ++ for (i in 1..pattern.length - 1) { ++ while (matches > 0 && pattern[matches] != pattern[i]) { ++ matches = resultTable[matches] ++ } ++ ++ if (pattern[matches] == pattern[i]) { ++ matches++ ++ } ++ resultTable[i] = matches ++ } ++ ++ return resultTable ++} ++ ++/** ++ * Returns a list of indices where the pattern occurs in this String. This method ++ * searches character by character and thus does not support regular expressions ++ * as input for the pattern. ++ * ++ * @param [pattern] The pattern to look for in this String. Regular expressions ++ * are not supported ++ * @param [ignoreCase] If true, characters are matched even if one is upper and the other is ++ * lower case ++ * ++ * @return A list of indices where the supplied [pattern] starts in the text. ++ */ ++public fun CharSequence.occurrencesOf(pattern: CharSequence, ignoreCase: Boolean = false): Sequence { ++ ++ if (pattern.isEmpty() || pattern.length > this.length) { ++ return emptySequence()","I believe this should be consistent with the result of `Regex("""").findAll(input = ""...."")`, i.e. a match in every position. +",2016-02-17 02:35:56 +528,"@@ -1162,3 +1162,84 @@ public fun CharSequence.lineSequence(): Sequence = splitToSequence(""\r\n + * * Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ + public fun CharSequence.lines(): List = lineSequence().toList() ++ ++/** ++ * For each i in [0, length), this function computes ++ * the length of the longest suffix of a substring of pattern from 0 to i ++ * that is also a prefix of the pattern itself. ++ */ ++private fun computePrefixFunction(pattern: CharSequence): IntArray { ++ val resultTable = IntArray(pattern.length) ++ ++ var matches = 0 ++ for (i in 1..pattern.length - 1) { ++ while (matches > 0 && pattern[matches] != pattern[i]) { ++ matches = resultTable[matches] ++ } ++ ++ if (pattern[matches] == pattern[i]) { ++ matches++ ++ } ++ resultTable[i] = matches ++ } ++ ++ return resultTable ++} ++ ++/** ++ * Returns a list of indices where the pattern occurs in this String. This method ++ * searches character by character and thus does not support regular expressions ++ * as input for the pattern. ++ * For a pattern longer than the text, an empty sequence is returned. If the pattern ++ * is empty, all indices are matched. ++ * ++ * @param [pattern] The pattern to look for in this String. Regular expressions ++ * are not supported ++ * @param [ignoreCase] If true, characters are matched even if one is upper and the other is ++ * lower case ++ * @param [matchOverlapping] If true, also match overlapping occurences. ++ * ++ * @return A list of indices where the supplied [pattern] starts in the text. ++ */ ++public fun CharSequence.occurrencesOf(pattern: CharSequence, ignoreCase: Boolean = false, matchOverlapping: Boolean = false): Sequence { ++ ++ if (pattern.length > this.length) { ++ return emptySequence() ++ } ++ ++ if (pattern.isEmpty()) { ++ return indices.asSequence()","It should be `(0..length).asSequence()`, because you need to count an empty match before the first character and empty one after the last characater. +",2016-03-02 18:56:47 +529,"@@ -1162,3 +1162,84 @@ public fun CharSequence.lineSequence(): Sequence = splitToSequence(""\r\n + * * Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ + public fun CharSequence.lines(): List = lineSequence().toList() ++ ++/** ++ * For each i in [0, length), this function computes ++ * the length of the longest suffix of a substring of pattern from 0 to i ++ * that is also a prefix of the pattern itself. ++ */ ++private fun computePrefixFunction(pattern: CharSequence): IntArray { ++ val resultTable = IntArray(pattern.length) ++ ++ var matches = 0 ++ for (i in 1..pattern.length - 1) { ++ while (matches > 0 && pattern[matches] != pattern[i]) { ++ matches = resultTable[matches] ++ } ++ ++ if (pattern[matches] == pattern[i]) { ++ matches++ ++ } ++ resultTable[i] = matches ++ } ++ ++ return resultTable ++} ++ ++/** ++ * Returns a list of indices where the pattern occurs in this String. This method ++ * searches character by character and thus does not support regular expressions ++ * as input for the pattern. ++ * For a pattern longer than the text, an empty sequence is returned. If the pattern ++ * is empty, all indices are matched. ++ * ++ * @param [pattern] The pattern to look for in this String. Regular expressions ++ * are not supported ++ * @param [ignoreCase] If true, characters are matched even if one is upper and the other is ++ * lower case ++ * @param [matchOverlapping] If true, also match overlapping occurences. ++ * ++ * @return A list of indices where the supplied [pattern] starts in the text. ++ */ ++public fun CharSequence.occurrencesOf(pattern: CharSequence, ignoreCase: Boolean = false, matchOverlapping: Boolean = false): Sequence { ++ ++ if (pattern.length > this.length) { ++ return emptySequence() ++ } ++ ++ if (pattern.isEmpty()) { ++ return indices.asSequence() ++ } ++ ++ if (pattern.length == 1) { ++ return indices.asSequence().filter { this[it].equals(pattern[0], ignoreCase) }","We could extract `CharSequence.occurrencesOf(char: Char, ignoreCase)` function from here. +",2016-03-02 18:58:18 +558,"@@ -1162,3 +1162,97 @@ public fun CharSequence.lineSequence(): Sequence = splitToSequence(""\r\n + * * Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ + public fun CharSequence.lines(): List = lineSequence().toList() ++ ++/** ++ * For each i in [0, length), this function computes ++ * the length of the longest suffix of a substring of pattern from 0 to i ++ * that is also a prefix of the pattern itself. ++ */ ++private fun computePrefixFunction(pattern: CharSequence): IntArray {","I'm not sure the prefix function is computed correctly. For the following example ""ABCDABD"" it returns [0,0,0,0,1,2,0], while according to the [reference](https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm#Worked_example_of_the_table-building_algorithm) it should be [-1,0,0,0,0,1,2]. + +Also it loops infinitely on the input ""AAABAAB"". +",2016-05-17 19:15:22 +567,"@@ -1162,3 +1162,97 @@ public fun CharSequence.lineSequence(): Sequence = splitToSequence(""\r\n + * * Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ + public fun CharSequence.lines(): List = lineSequence().toList() ++ ++/** ++ * For each i in [0, length), this function computes ++ * the length of the longest suffix of a substring of pattern from 0 to i ++ * that is also a prefix of the pattern itself. ++ */ ++private fun computePrefixFunction(pattern: CharSequence): IntArray { ++ val resultTable = IntArray(pattern.length) ++ ++ var matches = 0 ++ for (i in 1..pattern.length - 1) { ++ while (matches > 0 && pattern[matches] != pattern[i]) { ++ matches = resultTable[matches - 1] ++ } ++ ++ if (pattern[matches] == pattern[i]) { ++ matches++ ++ } ++ resultTable[i] = matches ++ } ++ ++ return resultTable ++} ++ ++/** ++ * Returns a sequence of indices where the char occurs in this CharSequence. ++ * ++ * @param [char] The character to look for in the string ++ * @param [ignoreCase] If true, characters are matched even if one is upper and the other is ++ * lower case ++ * ++ * @return A list of indices where the supplied [char] occurs in the text. ++ */ ++public fun CharSequence.occurrencesOf(char: Char, ignoreCase: Boolean = false): Sequence { ++ return indices.asSequence().filter { this[it].equals(char, ignoreCase) } ++} ++ ++/** ++ * Returns a sequence of indices where the pattern occurs in this CharSequence. This method ++ * searches character by character and thus does not support regular expressions ++ * as input for the pattern. ++ * For a pattern longer than the text, an empty sequence is returned. If the pattern ++ * is empty, all indices plus an empty occurrence at the end are matched. ++ * ++ * @param [pattern] The pattern to look for in this String. Regular expressions ++ * are not supported ++ * @param [ignoreCase] If true, characters are matched even if one is upper and the other is ++ * lower case ++ * @param [matchOverlapping] If true, also match overlapping occurrences. ++ * ++ * @return A list of indices where the supplied [pattern] starts in the text. ++ */ ++public fun CharSequence.occurrencesOf(pattern: CharSequence, ignoreCase: Boolean = false, matchOverlapping: Boolean = false): Sequence { ++ ++ if (pattern.length > this.length) { ++ return emptySequence() ++ } ++ ++ if (pattern.isEmpty()) { ++ return (0..length).asSequence() ++ } ++ ++ if (pattern.length == 1) { ++ return occurrencesOf(pattern[0], ignoreCase) ++ } ++ ++ // Non-trivial pattern matching, perform computation ++ // using Knuth-Morris-Pratt ++ ++ val prefixFunction = computePrefixFunction(pattern) ++ ++ var i = 0 ++ var matches = 0 ++ return generateSequence { ++ while (i < length) { ++ while (matches > 0 && !pattern[matches].equals(this[i], ignoreCase)) { ++ matches = prefixFunction[matches - 1] ++ } ++ ++ if (pattern[matches].equals(this[i], ignoreCase)) { ++ matches++ ++ }","This approach requires two character comparisons per position when `matches > 0`. Is it possible to restructure the loop body? Also applies to `computePrefixFunction`. +",2016-05-18 20:09:24 +578,"@@ -117,7 +117,7 @@ and find classes or functions which are not documented very well and submit a pa + In particular it'd be great if all functions included a nice example of how to use it such as for the + hashMapOf() function. + This is implemented using the @sample +-macro to include code from a test function. This serves as a double win; the API gets better documented with nice examples to help new users and the code gets more test coverage. ++macro to include code from a test function. The benefits of this approach are twofold; First, the API's documentations is improved via beneficial examples that help new users and second, the code coverage is increased.","> documentations is + +Not sure if it's consistent: either ""documentations are"" or ""documentation is"" +",2016-06-07 15:57:33 +495,"@@ -117,9 +118,8 @@ public object KotlinCompilerRunner { + val stream = ByteArrayOutputStream() + val out = PrintStream(stream) + +-// Uncomment after resolving problems with parallel compilation and tests +-// if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY) == null) +-// System.setProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, """") ++ if (java.lang.Boolean.parseBoolean(System.getProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, ""false"")))","use `String#toBoolean()` +",2015-12-01 14:14:38 +5,"@@ -118,17 +119,33 @@ private static Integer doExec(@NotNull CompileContext context, @NotNull Compiler + context.addMessage(CompilerMessageCategory.ERROR, ""K2JSCompiler does not support multiple module source roots."", null, -1, -1); + return -1; + } +- String[] commandLineArgs = constructArguments(context.getProject(), context.getModuleOutputDirectory(module), roots[0]); ++ ++ VirtualFile outDir = context.getModuleOutputDirectory(module); ++ String outFile = outDir == null ? null : K2JSRunnerUtils.constructPathToGeneratedFile(context.getProject(), outDir.getPath()); ++ ++ String[] commandLineArgs = constructArguments(context.getProject(), outFile, roots[0]); + Object rc = invokeExecMethod(environment, out, context, commandLineArgs, ""org.jetbrains.jet.cli.js.K2JSCompiler""); ++ ++ if (outDir != null) { ++ outDir.refresh(false, true);","Can you please tell me what this is about? +",2012-05-15 18:35:31 +292,"@@ -1191,14 +1191,14 @@ public inline fun Iterable.takeWhile(predicate: (T) -> Boolean): List + } + + /** +- * Returns a stream containing first elements satisfying the given *predicate* ++ * Returns a stream containing first elements satisfying the given [predicate] + */ + public fun Stream.takeWhile(predicate: (T) -> Boolean): Stream { + return TakeWhileStream(this, predicate) + } + + /** +- * Returns a list containing first elements satisfying the given *predicate* ++ * Returns a string containing the first characters that satisfy the given [predicate]","""the first characters"", do not need ""the"" +",2015-02-09 15:53:46 +297,"@@ -12,7 +12,7 @@ public fun Enumeration.iterator(): Iterator = object : Iterator { + } + + /** +- * Returns the given iterator itself. This allows to use an instance of iterator in a ranged for-loop ++ * Returns the given iterator itself. This allows to use an instance of iterator in a ranged for-loop.","""ranged for-loop"" -> ""`for` loop"" +",2015-02-09 16:00:05 +124,"@@ -120,6 +129,39 @@ fun JetElement.wrapInBlock(): JetBlockExpression { + block.appendElement(this) + return block + } ++ ++fun JetExpressionImpl.findBlockInExpression(element: JetExpressionImpl, expressionType: String?): JetBlockExpression? {","Why are this and the following functions extensions, but you don't use `this` in them and require call sites to pass same value twice? +",2014-03-04 16:01:55 +125,"@@ -120,6 +129,39 @@ fun JetElement.wrapInBlock(): JetBlockExpression { + block.appendElement(this) + return block + } ++ ++fun JetExpressionImpl.findBlockInExpression(element: JetExpressionImpl, expressionType: String?): JetBlockExpression? { ++ val bodyNode = when (expressionType) { ++ ""if"" -> element.getNode().findChildByType(JetNodeTypes.THEN) ++ ""else"" -> element.getNode().findChildByType(JetNodeTypes.ELSE) ++ else -> element.getNode().findChildByType(JetNodeTypes.BODY) ++ } ++ if (bodyNode?.getPsi()?.getFirstChild() is JetBlockExpression) { ++ return bodyNode!!.getPsi()!!.getFirstChild() as JetBlockExpression ++ } ++ return null","Use the power of Kotlin :) Four lines can be replaced with `return bodyNode?.getPsi()?.getFirstChild() as? JetBlockExpression` +",2014-03-04 16:02:09 +126,"@@ -120,6 +129,39 @@ fun JetElement.wrapInBlock(): JetBlockExpression { + block.appendElement(this) + return block + } ++ ++fun JetExpressionImpl.findBlockInExpression(element: JetExpressionImpl, expressionType: String?): JetBlockExpression? { ++ val bodyNode = when (expressionType) { ++ ""if"" -> element.getNode().findChildByType(JetNodeTypes.THEN) ++ ""else"" -> element.getNode().findChildByType(JetNodeTypes.ELSE) ++ else -> element.getNode().findChildByType(JetNodeTypes.BODY) ++ } ++ if (bodyNode?.getPsi()?.getFirstChild() is JetBlockExpression) { ++ return bodyNode!!.getPsi()!!.getFirstChild() as JetBlockExpression ++ } ++ return null ++} ++ ++fun JetExpressionImpl.getExpressionType(element: JetExpressionImpl): String? {","""Expression type"" phrase usually means different thing, so this usage of it is misleading. Better to replace ""type"" word with ""kind"". Don't forget that you have this phrase in several other places. +Also, it's better to use enumeration instead of strings, because it's more type-safe. Enumeration can be named `ExpressionBlockKind` or something like this. +",2014-03-04 16:03:02 +255,"@@ -121,17 +164,16 @@ public open class KotlinCompile(): AbstractCompile() { + args.noOptimize = kotlinOptions.noOptimize + args.noCallAssertions = kotlinOptions.noCallAssertions + args.noParamAssertions = kotlinOptions.noParamAssertions ++ } + +- val messageCollector = GradleMessageCollector(getLogger()) +- getLogger().debug(""Calling compiler"") +- val exitCode = compiler.exec(messageCollector, Services.EMPTY, args) +- +- when (exitCode) { +- ExitCode.COMPILATION_ERROR -> throw GradleException(""Compilation error. See log for more details"") +- ExitCode.INTERNAL_ERROR -> throw GradleException(""Internal compiler error. See log for more details"") +- else -> {} +- } ++ private fun getJavaSourceRoots(): HashSet = getSource()","May be `List`? +",2014-11-11 18:08:20 +254,"@@ -121,17 +164,16 @@ public open class KotlinCompile(): AbstractCompile() { + args.noOptimize = kotlinOptions.noOptimize + args.noCallAssertions = kotlinOptions.noCallAssertions + args.noParamAssertions = kotlinOptions.noParamAssertions ++ } + +- val messageCollector = GradleMessageCollector(getLogger()) +- getLogger().debug(""Calling compiler"") +- val exitCode = compiler.exec(messageCollector, Services.EMPTY, args) +- +- when (exitCode) { +- ExitCode.COMPILATION_ERROR -> throw GradleException(""Compilation error. See log for more details"") +- ExitCode.INTERNAL_ERROR -> throw GradleException(""Internal compiler error. See log for more details"") +- else -> {} +- } ++ private fun getJavaSourceRoots(): HashSet = getSource() ++ .filter { isJava(it) } ++ .map { findSrcDirRoot(it) } ++ .filter { it != null }","May be replaced with `filterNotNull` +",2014-11-11 18:07:54 +890,"@@ -122,3 +124,47 @@ class KotlinEnterHandler: EnterHandlerDelegateAdapter() { + return false + } + } ++ ++class KotlinConvertToBodyEnterHandler : EnterHandlerDelegateAdapter() { ++ override fun preprocessEnter(file: PsiFile, editor: Editor, ++ caretOffset: Ref, caretAdvance: Ref, dataContext: DataContext, ++ originalHandler: EditorActionHandler?): EnterHandlerDelegate.Result { ++ if (file !is KtFile) return EnterHandlerDelegate.Result.Continue ++ if (!KotlinEditorOptions.getInstance().isEnableSmartConvertToBody) return EnterHandlerDelegate.Result.Continue ++ if (!EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, caretOffset.get(), ++ file.fileType)) return EnterHandlerDelegate.Result.Continue ++ ++ val document = editor.document ++ ++ //Let's check if it's special convert to body case.",This comments doesn't explain anything and can be dropped safely.,2017-07-12 10:02:55 +891,"@@ -122,3 +124,47 @@ class KotlinEnterHandler: EnterHandlerDelegateAdapter() { + return false + } + } ++ ++class KotlinConvertToBodyEnterHandler : EnterHandlerDelegateAdapter() { ++ override fun preprocessEnter(file: PsiFile, editor: Editor, ++ caretOffset: Ref, caretAdvance: Ref, dataContext: DataContext, ++ originalHandler: EditorActionHandler?): EnterHandlerDelegate.Result { ++ if (file !is KtFile) return EnterHandlerDelegate.Result.Continue ++ if (!KotlinEditorOptions.getInstance().isEnableSmartConvertToBody) return EnterHandlerDelegate.Result.Continue ++ if (!EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, caretOffset.get(), ++ file.fileType)) return EnterHandlerDelegate.Result.Continue ++ ++ val document = editor.document ++ ++ //Let's check if it's special convert to body case. ++ val prevOffset = caretOffset.get() - 1 ++ if (document.isTextAt(prevOffset, ""{"")) {",Please consider inverting `if`.,2017-07-12 10:04:52 +893,"@@ -122,3 +124,47 @@ class KotlinEnterHandler: EnterHandlerDelegateAdapter() { + return false + } + } ++ ++class KotlinConvertToBodyEnterHandler : EnterHandlerDelegateAdapter() { ++ override fun preprocessEnter(file: PsiFile, editor: Editor, ++ caretOffset: Ref, caretAdvance: Ref, dataContext: DataContext, ++ originalHandler: EditorActionHandler?): EnterHandlerDelegate.Result { ++ if (file !is KtFile) return EnterHandlerDelegate.Result.Continue ++ if (!KotlinEditorOptions.getInstance().isEnableSmartConvertToBody) return EnterHandlerDelegate.Result.Continue ++ if (!EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, caretOffset.get(), ++ file.fileType)) return EnterHandlerDelegate.Result.Continue ++ ++ val document = editor.document ++ ++ //Let's check if it's special convert to body case. ++ val prevOffset = caretOffset.get() - 1 ++ if (document.isTextAt(prevOffset, ""{"")) { ++ document.commit(file.project) ++ val element = file.findElementAt(prevOffset) ++ if (element != null && element.matchParents( ++ KtFunctionLiteral::class.java, ++ KtLambdaExpression::class.java, ++ KtDeclarationWithBody::class.java ++ )) { ++ val declaration = element.parent.parent.parent as KtDeclarationWithBody ++ if (!declaration.hasDeclaredReturnType()) return EnterHandlerDelegate.Result.Continue",I think this restriction leaves the majority of use-cases out of scope. Can we overcome it? I'm not sure it all worth it without the solution.,2017-07-12 10:43:03 +894,"@@ -122,3 +124,47 @@ class KotlinEnterHandler: EnterHandlerDelegateAdapter() { + return false + } + } ++ ++class KotlinConvertToBodyEnterHandler : EnterHandlerDelegateAdapter() { ++ override fun preprocessEnter(file: PsiFile, editor: Editor, ++ caretOffset: Ref, caretAdvance: Ref, dataContext: DataContext, ++ originalHandler: EditorActionHandler?): EnterHandlerDelegate.Result { ++ if (file !is KtFile) return EnterHandlerDelegate.Result.Continue ++ if (!KotlinEditorOptions.getInstance().isEnableSmartConvertToBody) return EnterHandlerDelegate.Result.Continue ++ if (!EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, caretOffset.get(), ++ file.fileType)) return EnterHandlerDelegate.Result.Continue ++ ++ val document = editor.document ++ ++ //Let's check if it's special convert to body case. ++ val prevOffset = caretOffset.get() - 1 ++ if (document.isTextAt(prevOffset, ""{"")) { ++ document.commit(file.project) ++ val element = file.findElementAt(prevOffset) ++ if (element != null && element.matchParents( ++ KtFunctionLiteral::class.java, ++ KtLambdaExpression::class.java, ++ KtDeclarationWithBody::class.java ++ )) { ++ val declaration = element.parent.parent.parent as KtDeclarationWithBody ++ if (!declaration.hasDeclaredReturnType()) return EnterHandlerDelegate.Result.Continue ++ val equals = declaration.equalsToken ++ if (equals != null) { ++ val startOffset =",Will it work with comments? Maybe it would be better to check for '=' and extend it with spaces from left and right.,2017-07-12 10:44:30 +850,"@@ -124,21 +128,71 @@ class ConvertTwoComparisonsToRangeCheckIntention : SelfTargetingOffsetIndependen + // To avoid possible side effects + if (!min.isSimple() || !max.isSimple()) return null + ++ val valContext = value.analyze()",You don't need to call `analyze()` multiple times; calling it once will return a `BindingContext` with information about all the expressions.,2017-05-08 13:06:34 +851,"@@ -124,21 +128,71 @@ class ConvertTwoComparisonsToRangeCheckIntention : SelfTargetingOffsetIndependen + // To avoid possible side effects + if (!min.isSimple() || !max.isSimple()) return null + ++ val valContext = value.analyze() ++ val minContext = min.analyze() ++ val maxContext = max.analyze() ++ val valType = value.getType(valContext) ++ val minType = min.getType(minContext) ++ val maxType = max.getType(maxContext) ++ ++ if (valType == null || minType == null || maxType == null) return null ++ ++ if (!valType.isComparable()) return null ++ ++ var minVal = min ++ var maxVal = max ++ ++ if (minType != valType || maxType != valType) { ++ //numbers can be compared to numbers of different types ++ if (valType.isPrimitiveNumberType() && minType.isPrimitiveNumberType() && maxType.isPrimitiveNumberType()) { ++ //char is comparable to chars only ++ if (KotlinBuiltIns.isChar(valType) || KotlinBuiltIns.isChar(minType) || KotlinBuiltIns.isChar(maxType)) return null ++ ++ if (valType.isFloatingPoint()) { ++ if (minType.isInteger()) ++ minVal = KtPsiFactory(minVal).createExpression(getDoubleConstant(min, minType, minContext) ?: return null) ++ if (maxType.isInteger()) ++ maxVal = KtPsiFactory(maxVal).createExpression(getDoubleConstant(max, maxType, maxContext) ?: return null) ++ } ++ } else { ++ return null ++ } ++ } ++ + if (incrementMinByOne || decrementMaxByOne) { +- if (!value.getType(value.analyze()).isValidTypeForIncrementDecrementByOne()) return null ++ if (!valType.isValidTypeForIncrementDecrementByOne()) return null + } + +- val minText = if (incrementMinByOne) min.getChangeBy(1) else min.text +- val maxText = if (decrementMaxByOne) max.getChangeBy(-1) else max.text ++ val minText = if (incrementMinByOne) minVal.getChangeBy(1) else minVal.text ++ val maxText = if (decrementMaxByOne) maxVal.getChangeBy(-1) else maxVal.text + return RangeExpressionData(value, minText ?: return null, maxText ?: return null) + } + +- private fun KotlinType?.isValidTypeForIncrementDecrementByOne(): Boolean { +- this ?: return false ++ private fun getDoubleConstant(intExpr: KtExpression, type: KotlinType, context: BindingContext): String? { ++ val intConst = ConstantExpressionEvaluator.getConstant(intExpr, context)?.getValue(type) ?: return null ++ return (intConst as? Number)?.toDouble()?.toString() ++ } ++ ++ private fun KotlinType.isComparable(): Boolean {","`DescriptorUtils.isSubtypeOfClass(this, expression.builtIns.getComparable())`",2017-05-08 13:09:47 +325,"@@ -126,32 +254,100 @@ public trait MutableSet : Set, MutableCollection { + override fun clear(): Unit + } + ++/** ++ * A collection that holds pairs of objects (keys and values) and supports efficiently retrieving ++ * the value corresponding to each key. Map keys are unique; the map holds only one value for each key. ++ * Methods in this trait support only read-only access to the map; read-write access is supported through ++ * the [MutableMap] trait. ++ */ + public trait Map { + // Query Operations ++ /** ++ * Returns the size of the map. ++ */","size is a little bit unclear, may be ""number of key-value"" pairs? +",2015-03-02 17:30:23 +326,"@@ -126,32 +254,100 @@ public trait MutableSet : Set, MutableCollection { + override fun clear(): Unit + } + ++/** ++ * A collection that holds pairs of objects (keys and values) and supports efficiently retrieving ++ * the value corresponding to each key. Map keys are unique; the map holds only one value for each key. ++ * Methods in this trait support only read-only access to the map; read-write access is supported through ++ * the [MutableMap] trait. ++ */ + public trait Map { + // Query Operations ++ /** ++ * Returns the size of the map. ++ */ + public fun size(): Int ++ ++ /** ++ * Returns `true` if the map is empty (contains no elements), `false` otherwise. ++ */ + public fun isEmpty(): Boolean ++ ++ /** ++ * Returns `true` if the map contains the specified [key]. ++ */ + public fun containsKey(key: Any?): Boolean ++ ++ /** ++ * Returns `true` if the map maps one or more keys to the specified [value]. ++ */ + public fun containsValue(value: Any?): Boolean ++ ++ /** ++ * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map. ++ */ + public fun get(key: Any?): V? + + // Views ++ /** ++ * Returns a [Set] of all keys in this map. ++ */ + public fun keySet(): Set ++ ++ /** ++ * Returns a [Collection] of all values in this map. ++ */ + public fun values(): Collection","May contain duplicate values +",2015-03-02 17:31:59 +470,"@@ -128,36 +128,71 @@ private static String execCompiler( + + String[] argsArray = ArrayUtil.toStringArray(argumentsList); + +- // trying the daemon first +- if (incrementalCaches != null && RmiPackage.isDaemonEnabled()) { +- File libPath = CompilerRunnerUtil.getLibPath(environment.getKotlinPaths(), messageCollector); +- // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ +- // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler +- CompilerId compilerId = CompilerId.makeCompilerId(new File(libPath, ""kotlin-compiler.jar"")); +- DaemonOptions daemonOptions = RmiPackage.configureDaemonOptions(); +- DaemonJVMOptions daemonJVMOptions = RmiPackage.configureDaemonLaunchingOptions(true); +- // TODO: find proper stream to report daemon connection progress +- CompileService daemon = KotlinCompilerClient.Companion.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, System.out, true, true); +- if (daemon != null) { +- Integer res = KotlinCompilerClient.Companion.incrementalCompile(daemon, argsArray, incrementalCaches, out); +- return res.toString(); +- } +- } ++ if (!tryCompileWithDaemon(messageCollector, collector, environment, incrementalCaches, argsArray)) { ++ // otherwise fallback to in-process + +- // otherwise fallback to in-process ++ ByteArrayOutputStream stream = new ByteArrayOutputStream(); ++ PrintStream out = new PrintStream(stream); + +- Object rc = CompilerRunnerUtil.invokeExecMethod( +- compilerClassName, argsArray, environment, messageCollector, out +- ); ++ Object rc = CompilerRunnerUtil.invokeExecMethod( compilerClassName, argsArray, environment, messageCollector, out); + +- // exec() returns an ExitCode object, class of which is loaded with a different class loader, +- // so we take it's contents through reflection +- return getReturnCodeFromObject(rc); ++ // exec() returns an ExitCode object, class of which is loaded with a different class loader, ++ // so we take it's contents through reflection ++ ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc)); ++ } + } + catch (Throwable e) { + MessageCollectorUtil.reportException(messageCollector, e); +- return INTERNAL_ERROR; ++ reportInternalCompilerError(messageCollector); ++ } ++ } ++ ++ private static boolean tryCompileWithDaemon( ++ MessageCollector messageCollector, ++ OutputItemsCollector collector, ++ CompilerEnvironment environment, ++ Map incrementalCaches, ++ String[] argsArray ++ ) throws IOException { ++ if (incrementalCaches != null && RmiPackage.isDaemonEnabled()) { ++ File libPath = CompilerRunnerUtil.getLibPath(environment.getKotlinPaths(), messageCollector); ++ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ ++ // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler ++ CompilerId compilerId = CompilerId.makeCompilerId(new File(libPath, ""kotlin-compiler.jar"")); ++ DaemonOptions daemonOptions = RmiPackage.configureDaemonOptions(); ++ DaemonJVMOptions daemonJVMOptions = RmiPackage.configureDaemonJVMOptions(true); ++ ++ ArrayList daemonReportMessages = new ArrayList(); ++ ++ CompileService daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, new DaemonReportingTargets(null, daemonReportMessages), true, true); ++ ++ for (DaemonReportMessage msg: daemonReportMessages) { ++ if (msg.getCategory() == DaemonReportCategory.EXCEPTION && daemon == null) { ++ messageCollector.report(CompilerMessageSeverity.INFO, ++ ""Falling back to compilation without daemon due to error: "" + msg.getMessage(), ++ CompilerMessageLocation.NO_LOCATION); ++ } ++ else { ++ messageCollector.report(CompilerMessageSeverity.INFO, msg.getMessage(), CompilerMessageLocation.NO_LOCATION); ++ } ++ } ++ ++ if (daemon != null) { ++ ByteArrayOutputStream compilerOut = new ByteArrayOutputStream(); ++ ByteArrayOutputStream daemonOut = new ByteArrayOutputStream(); ++ ++ Integer res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, incrementalCaches, compilerOut, daemonOut); ++ ++ ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString()); ++ BufferedReader reader = new BufferedReader(new StringReader(daemonOut.toString()));","will we see non-latin characters? it could be significant for error messages with path to files, for example +",2015-09-08 18:24:39 +318,"@@ -13,39 +13,45 @@ public fun InputStream.iterator(): ByteIterator = + public override fun nextByte(): Byte = read().toByte() + } + +-/** Creates a buffered input stream */ ++/** ++ * Creates a buffered input stream wrapping this stream. ++ * @param bufferSize the buffer size to use. ++ */ + public fun InputStream.buffered(bufferSize: Int = defaultBufferSize): InputStream + = if (this is BufferedInputStream) + this + else + BufferedInputStream(this, bufferSize) + +-/** Creates a reader on an input stream using UTF-8 or specified charset. */ ++/** Creates a reader on this input stream using UTF-8 or the specified [charset]. */","Need to put it in conventions, wording around documenting parameter with default value. +",2015-02-11 08:38:03 +534,"@@ -13,79 +13,96 @@ class ParsePrimitivesJVMTest { + } + + @test fun toByte() { +- assertEqualsOrFailsNullable(77.toByte(), ""+77"", String::toByte, String::toByteOrNull) +- assertEqualsOrFailsNullable(Byte.MIN_VALUE, ""-128"", String::toByte, String::toByteOrNull) +- assertEqualsOrFailsNullable(null, ""128"", String::toByte, String::toByteOrNull) ++ CompareBehaviourContext(String::toByte, String::toByteOrNull).apply { ++ ++ assertProduce(77.toByte(), ""+77"") ++ assertProduce(Byte.MIN_VALUE, ""-128"") ++ assertProduce(null, ""128"") ++ } + } + + @test fun toShort() { +- assertEqualsOrFailsNullable(77.toShort(), ""77"", String::toShort, String::toShortOrNull) +- assertEqualsOrFailsNullable(Short.MIN_VALUE, ""-32768"", String::toShort, String::toShortOrNull) +- assertEqualsOrFailsNullable(null, ""+32768"", String::toShort, String::toShortOrNull) ++ CompareBehaviourContext(String::toShort, String::toShortOrNull).apply { ++ ++ assertProduce(77.toShort(), ""77"") ++ assertProduce(Short.MIN_VALUE, ""-32768"") ++ assertProduce(null, ""+32768"") ++ } + } + + @test fun toInt() { +- assertEqualsOrFailsNullable(77, ""77"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(Int.MAX_VALUE, ""+2147483647"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(Int.MIN_VALUE, ""-2147483648"", String::toInt, String::toIntOrNull) ++ CompareBehaviourContext(String::toInt, String::toIntOrNull).apply { ++ ++ assertProduce(77, ""77"") ++ assertProduce(Int.MAX_VALUE, ""+2147483647"") ++ assertProduce(Int.MIN_VALUE, ""-2147483648"") + +- assertEqualsOrFailsNullable(null, ""2147483648"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(null, ""-2147483649"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(null, ""239239kotlin"", String::toInt, String::toIntOrNull) ++ assertProduce(null, ""2147483648"") ++ assertProduce(null, ""-2147483649"") ++ assertProduce(null, ""239239kotlin"") ++ } + } + + @test fun toLong() { +- assertEqualsOrFailsNullable(77.toLong(), ""77"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(Long.MAX_VALUE, ""+9223372036854775807"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(Long.MIN_VALUE, ""-9223372036854775808"", String::toLong, String::toLongOrNull) +- +- assertEqualsOrFailsNullable(null, ""9223372036854775808"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""-9223372036854775809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""922337 75809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""92233,75809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""92233`75809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""-922337KOTLIN775809"", String::toLong, String::toLongOrNull) ++ CompareBehaviourContext(String::toLong, String::toLongOrNull).apply { ++ ++ assertProduce(77.toLong(), ""77"") ++ assertProduce(Long.MAX_VALUE, ""+9223372036854775807"") ++ assertProduce(Long.MIN_VALUE, ""-9223372036854775808"") ++ ++ assertProduce(null, ""9223372036854775808"") ++ assertProduce(null, ""-9223372036854775809"") ++ assertProduce(null, ""922337 75809"") ++ assertProduce(null, ""92233,75809"") ++ assertProduce(null, ""92233`75809"") ++ assertProduce(null, ""-922337KOTLIN775809"") ++ } + } + + @test fun toFloat() { +- assertEqualsOrFailsNullable(77.0f, ""77.0"", String::toFloat, String::toFloatOrNull) +- assertEqualsOrFailsNullable(Float.NEGATIVE_INFINITY, ""-1e39"", String::toFloat, String::toFloatOrNull) +- assertEqualsOrFailsNullable(Float.POSITIVE_INFINITY, ""1000000000000000000000000000000000000000"", +- String::toFloat, String::toFloatOrNull) ++ CompareBehaviourContext(String::toFloat, String::toFloatOrNull).apply { + +- assertEqualsOrFailsNullable(null, ""dark side"", String::toFloat, String::toFloatOrNull) ++ assertProduce(77.0f, ""77.0"") ++ assertProduce(Float.NEGATIVE_INFINITY, ""-1e39"") ++ assertProduce(Float.POSITIVE_INFINITY, ""1000000000000000000000000000000000000000"") ++ assertProduce(null, ""dark side"") ++ } + } + + @test fun toDouble() { +- assertEqualsOrFailsNullable(-77.0, ""-77"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""77."", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""77.0"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(-1.77, ""-1.77"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(0.77, ""+.77"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(-77.0, ""\t-77 \n"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""7.7e1"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""+770e-1"", String::toDouble, String::toDoubleOrNull) +- +- assertEqualsOrFailsNullable(-Double.NaN, ""-NaN"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(Double.POSITIVE_INFINITY, ""+Infinity"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable((0x77 shl 1).toDouble(), ""0x77p1"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(0x77.toDouble(), ""0x.77P8"", String::toDouble, String::toDoubleOrNull) +- +- assertEqualsOrFailsNullable(null, ""7..7"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(null, ""0x77e1"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(null, ""007 not a number"", String::toDouble, String::toDoubleOrNull) ++ CompareBehaviourContext(String::toDouble, String::toDoubleOrNull).apply { ++ ++ assertProduce(-77.0, ""-77"") ++ assertProduce(77.0, ""77."") ++ assertProduce(77.0, ""77.0"") ++ assertProduce(-1.77, ""-1.77"") ++ assertProduce(0.77, ""+.77"") ++ assertProduce(-77.0, ""\t-77 \n"") ++ assertProduce(77.0, ""7.7e1"") ++ assertProduce(77.0, ""+770e-1"") ++ ++ assertProduce(-Double.NaN, ""-NaN"") ++ assertProduce(Double.POSITIVE_INFINITY, ""+Infinity"") ++ assertProduce((0x77 shl 1).toDouble(), ""0x77p1"") ++ assertProduce(0x77.toDouble(), ""0x.77P8"") ++ ++ assertProduce(null, ""7..7"") ++ assertProduce(null, ""0x77e1"") ++ assertProduce(null, ""007 not a number"") ++ } + } + } + +-private inline fun assertEqualsOrFailsNullable(output: T?, +- input: String, +- crossinline converOrFail: (String) -> T, +- crossinline convertOrNull: (String) -> T?) { +- if(output == null) { +- assertFails { converOrFail(input) } +- assertNull (convertOrNull(input) ) +- } else { +- assertEquals(output, converOrFail(input)) +- assertEquals(output, convertOrNull(input)) ++ ++private class CompareBehaviourContext(val convertOrFail: (String) -> T,","`Behaviour` we prefer American English in identifiers :) +",2016-03-30 18:24:39 +533,"@@ -13,79 +13,96 @@ class ParsePrimitivesJVMTest { + } + + @test fun toByte() { +- assertEqualsOrFailsNullable(77.toByte(), ""+77"", String::toByte, String::toByteOrNull) +- assertEqualsOrFailsNullable(Byte.MIN_VALUE, ""-128"", String::toByte, String::toByteOrNull) +- assertEqualsOrFailsNullable(null, ""128"", String::toByte, String::toByteOrNull) ++ CompareBehaviourContext(String::toByte, String::toByteOrNull).apply { ++ ++ assertProduce(77.toByte(), ""+77"") ++ assertProduce(Byte.MIN_VALUE, ""-128"") ++ assertProduce(null, ""128"") ++ } + } + + @test fun toShort() { +- assertEqualsOrFailsNullable(77.toShort(), ""77"", String::toShort, String::toShortOrNull) +- assertEqualsOrFailsNullable(Short.MIN_VALUE, ""-32768"", String::toShort, String::toShortOrNull) +- assertEqualsOrFailsNullable(null, ""+32768"", String::toShort, String::toShortOrNull) ++ CompareBehaviourContext(String::toShort, String::toShortOrNull).apply { ++ ++ assertProduce(77.toShort(), ""77"") ++ assertProduce(Short.MIN_VALUE, ""-32768"") ++ assertProduce(null, ""+32768"") ++ } + } + + @test fun toInt() { +- assertEqualsOrFailsNullable(77, ""77"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(Int.MAX_VALUE, ""+2147483647"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(Int.MIN_VALUE, ""-2147483648"", String::toInt, String::toIntOrNull) ++ CompareBehaviourContext(String::toInt, String::toIntOrNull).apply { ++ ++ assertProduce(77, ""77"") ++ assertProduce(Int.MAX_VALUE, ""+2147483647"") ++ assertProduce(Int.MIN_VALUE, ""-2147483648"") + +- assertEqualsOrFailsNullable(null, ""2147483648"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(null, ""-2147483649"", String::toInt, String::toIntOrNull) +- assertEqualsOrFailsNullable(null, ""239239kotlin"", String::toInt, String::toIntOrNull) ++ assertProduce(null, ""2147483648"") ++ assertProduce(null, ""-2147483649"") ++ assertProduce(null, ""239239kotlin"") ++ } + } + + @test fun toLong() { +- assertEqualsOrFailsNullable(77.toLong(), ""77"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(Long.MAX_VALUE, ""+9223372036854775807"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(Long.MIN_VALUE, ""-9223372036854775808"", String::toLong, String::toLongOrNull) +- +- assertEqualsOrFailsNullable(null, ""9223372036854775808"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""-9223372036854775809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""922337 75809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""92233,75809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""92233`75809"", String::toLong, String::toLongOrNull) +- assertEqualsOrFailsNullable(null, ""-922337KOTLIN775809"", String::toLong, String::toLongOrNull) ++ CompareBehaviourContext(String::toLong, String::toLongOrNull).apply { ++ ++ assertProduce(77.toLong(), ""77"") ++ assertProduce(Long.MAX_VALUE, ""+9223372036854775807"") ++ assertProduce(Long.MIN_VALUE, ""-9223372036854775808"") ++ ++ assertProduce(null, ""9223372036854775808"") ++ assertProduce(null, ""-9223372036854775809"") ++ assertProduce(null, ""922337 75809"") ++ assertProduce(null, ""92233,75809"") ++ assertProduce(null, ""92233`75809"") ++ assertProduce(null, ""-922337KOTLIN775809"") ++ } + } + + @test fun toFloat() { +- assertEqualsOrFailsNullable(77.0f, ""77.0"", String::toFloat, String::toFloatOrNull) +- assertEqualsOrFailsNullable(Float.NEGATIVE_INFINITY, ""-1e39"", String::toFloat, String::toFloatOrNull) +- assertEqualsOrFailsNullable(Float.POSITIVE_INFINITY, ""1000000000000000000000000000000000000000"", +- String::toFloat, String::toFloatOrNull) ++ CompareBehaviourContext(String::toFloat, String::toFloatOrNull).apply { + +- assertEqualsOrFailsNullable(null, ""dark side"", String::toFloat, String::toFloatOrNull) ++ assertProduce(77.0f, ""77.0"") ++ assertProduce(Float.NEGATIVE_INFINITY, ""-1e39"") ++ assertProduce(Float.POSITIVE_INFINITY, ""1000000000000000000000000000000000000000"") ++ assertProduce(null, ""dark side"") ++ } + } + + @test fun toDouble() { +- assertEqualsOrFailsNullable(-77.0, ""-77"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""77."", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""77.0"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(-1.77, ""-1.77"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(0.77, ""+.77"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(-77.0, ""\t-77 \n"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""7.7e1"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(77.0, ""+770e-1"", String::toDouble, String::toDoubleOrNull) +- +- assertEqualsOrFailsNullable(-Double.NaN, ""-NaN"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(Double.POSITIVE_INFINITY, ""+Infinity"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable((0x77 shl 1).toDouble(), ""0x77p1"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(0x77.toDouble(), ""0x.77P8"", String::toDouble, String::toDoubleOrNull) +- +- assertEqualsOrFailsNullable(null, ""7..7"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(null, ""0x77e1"", String::toDouble, String::toDoubleOrNull) +- assertEqualsOrFailsNullable(null, ""007 not a number"", String::toDouble, String::toDoubleOrNull) ++ CompareBehaviourContext(String::toDouble, String::toDoubleOrNull).apply { ++ ++ assertProduce(-77.0, ""-77"") ++ assertProduce(77.0, ""77."") ++ assertProduce(77.0, ""77.0"") ++ assertProduce(-1.77, ""-1.77"") ++ assertProduce(0.77, ""+.77"") ++ assertProduce(-77.0, ""\t-77 \n"") ++ assertProduce(77.0, ""7.7e1"") ++ assertProduce(77.0, ""+770e-1"") ++ ++ assertProduce(-Double.NaN, ""-NaN"") ++ assertProduce(Double.POSITIVE_INFINITY, ""+Infinity"") ++ assertProduce((0x77 shl 1).toDouble(), ""0x77p1"") ++ assertProduce(0x77.toDouble(), ""0x.77P8"") ++ ++ assertProduce(null, ""7..7"") ++ assertProduce(null, ""0x77e1"") ++ assertProduce(null, ""007 not a number"") ++ } + } + } + +-private inline fun assertEqualsOrFailsNullable(output: T?, +- input: String, +- crossinline converOrFail: (String) -> T, +- crossinline convertOrNull: (String) -> T?) { +- if(output == null) { +- assertFails { converOrFail(input) } +- assertNull (convertOrNull(input) ) +- } else { +- assertEquals(output, converOrFail(input)) +- assertEquals(output, convertOrNull(input)) ++ ++private class CompareBehaviourContext(val convertOrFail: (String) -> T, ++ val convertOrNull: (String) -> T?) { ++ fun assertProduce(output: T?, input: String) { ++ if(output == null) { ++ assertFails { convertOrFail(input) }","Please specify input string in the detail message, i.e. something like ""Expected to fail (or return null) on $input"" +",2016-03-30 18:17:46 +295,"@@ -13,8 +13,8 @@ private enum class State { + } + + /** +- * A base class to simplify implementing iterators so that implementations only have to implement [[computeNext()]] +- * to implement the iterator, calling [[done()]] when the iteration is complete. ++ * A base class to simplify implementing iterators so that implementations only have to implement [computeNext]","Warning, using this class has performance penalty compared to plain raw implementation per case, measured with JMH when operation per element is relatively cheap. +",2015-02-09 15:56:52 +676,"@@ -132,50 +132,34 @@ public inline fun println() { + System.out.println() + } + +-// Since System.in can change its value on the course of program running, +-// we should always delegate to current value and cannot just pass it to InputStreamReader constructor. +-// We could use ""by"" implementation, but we can only use ""by"" with interfaces and InputStream is abstract class. +-private val stdin: BufferedReader by lazy { BufferedReader(InputStreamReader(object : InputStream() { +- public override fun read(): Int { +- return System.`in`.read() +- } +- +- public override fun reset() { +- System.`in`.reset() +- } +- +- public override fun read(b: ByteArray): Int { +- return System.`in`.read(b) +- } +- +- public override fun close() { +- System.`in`.close() +- } +- +- public override fun mark(readlimit: Int) { +- System.`in`.mark(readlimit) +- } +- +- public override fun skip(n: Long): Long { +- return System.`in`.skip(n) +- } +- +- public override fun available(): Int { +- return System.`in`.available() +- } +- +- public override fun markSupported(): Boolean { +- return System.`in`.markSupported() +- } +- +- public override fun read(b: ByteArray, off: Int, len: Int): Int { +- return System.`in`.read(b, off, len) +- } +-}))} +- + /** + * Reads a line of input from the standard input stream. + * + * @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached. + */ +-public fun readLine(): String? = stdin.readLine() ++ ++public fun readLine(): String? { ++ val buffer = StringBuilder() ++ var c = System.`in`.read() ++ if(c < 0) return null ++ buffer.append(c.toChar()) ++ do { ++ c = System.`in`.read() ++ if(c < 0) return buffer.toString() ++ val ch = c.toChar()","Unfortunately, this will work only for US-ASCII encoding. ",2016-12-29 23:07:06 +50,"@@ -132,7 +132,10 @@ map.platform.class.to.kotlin=Change all usages of ''{0}'' in this file to ''{1}' + map.platform.class.to.kotlin.multiple=Change all usages of ''{0}'' in this file to a Kotlin class + map.platform.class.to.kotlin.advertisement=Choose an appropriate Kotlin class + map.platform.class.to.kotlin.family=Change to Kotlin class +- ++create.from.usage.family=Create from usage ++create.method.from.usage=Create method ''{0}'' from usage","In Kotlin, we call them functions, not methods. Please, rename it here and in other code. +",2013-04-26 11:10:47 +513,"@@ -132,8 +132,13 @@ class AndroidGradleWrapper { + && variantData.scope.getRenderscriptCompileTask() != null) { + result.add(variantData.scope.getRenderscriptSourceOutputDir()); + } ++ } + +- return result ++ def getExtraSourcesMethod = variantData.getMetaClass().getMetaMethod(""getExtraGeneratedSourceFolders"") ++ if (getExtraSourcesMethod.returnType.metaClass == List.metaClass) { ++ result.addAll(variantData.getExtraGeneratedSourceFolders())","variantData.getExtraGeneratedSourceFolders() is Nullable, so you should check for null, before calling addAll +",2016-02-12 08:47:33 +591,"@@ -133,15 +138,32 @@ public void execute() throws MojoExecutionException, MojoFailureException { + configureCompilerArguments(arguments, compiler); + printCompilerArgumentsIfDebugEnabled(arguments, compiler); + +- MessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); ++ MavenPluginLogMessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog(), true); + + ExitCode exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments); + + switch (exitCode) { + case COMPILATION_ERROR: +- throw new MojoExecutionException(""Compilation error. See log for more details""); + case INTERNAL_ERROR: +- throw new MojoExecutionException(""Internal compiler error. See log for more details""); ++ throw new KotlinCompilationFailureException( ++ CollectionsKt.map(messageCollector.getCollectedErrors(), new Function1, CompilerMessage>() {","Isn't compiler exception logged as error? +",2016-08-10 11:22:25 +590,"@@ -133,15 +138,32 @@ public void execute() throws MojoExecutionException, MojoFailureException { + configureCompilerArguments(arguments, compiler); + printCompilerArgumentsIfDebugEnabled(arguments, compiler); + +- MessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); ++ MavenPluginLogMessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog(), true); + + ExitCode exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments); + + switch (exitCode) { + case COMPILATION_ERROR: +- throw new MojoExecutionException(""Compilation error. See log for more details""); + case INTERNAL_ERROR: +- throw new MojoExecutionException(""Internal compiler error. See log for more details""); ++ throw new KotlinCompilationFailureException( ++ CollectionsKt.map(messageCollector.getCollectedErrors(), new Function1, CompilerMessage>() { ++ @Override ++ public CompilerMessage invoke(Pair pair) { ++ String lineContent = pair.getFirst().getLineContent(); ++ int lineContentLength = lineContent == null ? 0 : lineContent.length(); ++ ++ return new CompilerMessage( ++ pair.getFirst().getPath(), ++ CompilerMessage.Kind.ERROR, ++ pair.getFirst().getLine(),","Are they zero-based in `CompilerMessageLocation` ? +",2016-08-10 11:18:37 +592,"@@ -133,16 +137,32 @@ public void execute() throws MojoExecutionException, MojoFailureException { + configureCompilerArguments(arguments, compiler); + printCompilerArgumentsIfDebugEnabled(arguments, compiler); + +- MessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); ++ MavenPluginLogMessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); + + ExitCode exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments); + +- switch (exitCode) { +- case COMPILATION_ERROR: +- throw new MojoExecutionException(""Compilation error. See log for more details""); +- case INTERNAL_ERROR: +- throw new MojoExecutionException(""Internal compiler error. See log for more details""); +- default: ++ if (exitCode != ExitCode.OK) { ++ throw new KotlinCompilationFailureException( ++ CollectionsKt.map(messageCollector.getCollectedErrors(), new Function1, CompilerMessage>() { ++ @Override ++ public CompilerMessage invoke(Pair pair) { ++ CompilerMessageLocation location = pair.getFirst(); ++ String message = pair.getSecond(); ++ String lineContent = location.getLineContent(); ++ int lineContentLength = lineContent == null ? 0 : lineContent.length(); ++ ++ return new CompilerMessage( ++ location.getPath(), ++ CompilerMessage.Kind.ERROR,","yes, but in this case it looks not so clear that there is -1 and 0 with special meaning +",2016-08-10 14:35:44 +9,"@@ -133,8 +133,12 @@ private QuickFixes() {} + actions.put(VAL_WITH_SETTER, changeVariableMutabilityFix); + actions.put(VAL_REASSIGNMENT, changeVariableMutabilityFix); + +- actions.put(UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false)); +- actions.put(UNSAFE_CALL, new ReplaceCallFix(true)); ++ actions.put(UNNECESSARY_SAFE_CALL, new ReplaceCallFix(true, false)); ++ actions.put(UNSAFE_CALL, new ReplaceCallFix(true, true)); ++ actions.put(UNSAFE_CALL, new ReplaceCallFix(false, true));","Two booleans in parameters almost always look bad because it's difficult to read such code. It's better to provide static constructors like ReplaceCallFix.toDotCall(), ReplaceCallFix.toQuestionMarkCall(), ReplaceCallFix.toExclamationCall(). Another alternative is to create and pass as parameter some enumeration. +",2012-06-19 14:50:21 +11,"@@ -133,8 +133,14 @@ private QuickFixes() {} + actions.put(VAL_WITH_SETTER, changeVariableMutabilityFix); + actions.put(VAL_REASSIGNMENT, changeVariableMutabilityFix); + +- actions.put(UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false)); +- actions.put(UNSAFE_CALL, new ReplaceCallFix(true)); ++ actions.put(UNNECESSARY_SAFE_CALL, ReplaceCallFix.toDotCallFromSafeCall()); ++ actions.put(UNSAFE_CALL, ReplaceCallFix.toSafeCall()); ++ ++ actions.put(UNSAFE_CALL, ReplaceCallFix.toNonNullAssertedCall()); ++ actions.put(UNNECESSARY_NOT_NULL_ASSERTION, ReplaceCallFix.toDotCallFromNonNullAssertedCall()); ++ ++ actions.put(UNNECESSARY_NOT_NULL_ASSERTION, new UnnecessaryNotNullAssertionFix());","Both quick fixes are available for this code snippet: +fun test(value : String) : String { + return value!!.toString() +} + +I suggest to forbid one from UnnecessaryNotNullAssertionFix if warning is in the middle of DOT_QUALIFIED_EXPRESSION. + +By the way, Sergey, what tools do you use for monitoring PSI tree. I don't remember did I tell you about Tools->View PSI structure of current file? +",2012-06-26 20:19:10 +912,"@@ -135,4 +136,23 @@ public static KotlinSingleIntentionActionFactory createFactory() { + } + }; + } ++ ++ public static KotlinSingleIntentionActionFactory createLateInitFactory() {","Please convert this file to Kotlin if you're adding substantial new code to it. (Rename to .kt, commit, then rename back to .java, run J2K, make any changes needed for the project to compile, commit again, then make your changes.)",2017-07-24 12:48:44 +913,"@@ -135,4 +136,23 @@ public static KotlinSingleIntentionActionFactory createFactory() { + } + }; + } ++ ++ public static KotlinSingleIntentionActionFactory createLateInitFactory() { ++ return new KotlinSingleIntentionActionFactory() { ++ @Override ++ public KotlinQuickFixAction createAction(@NotNull Diagnostic diagnostic) { ++ PsiElement element = Errors.INAPPLICABLE_LATEINIT_MODIFIER.cast(diagnostic).getPsiElement(); ++ KtProperty property = PsiTreeUtil.getParentOfType(element, KtProperty.class); ++ if (property == null) return null; ++ ++ boolean hasInitializer = property.hasInitializer(); ++ boolean hasGetter = property.getGetter() != null && property.getGetter().getBodyExpression() != null;","The getter and setter checks are not needed. This quickfix should apply to any lateinit property; _late_init means that it's initialized somewhere in the class, and this applies to regular properties with default getters and setters too.",2017-07-24 12:52:05 +666,"@@ -135,7 +135,7 @@ public inline fun println() { + // Since System.in can change its value on the course of program running, + // we should always delegate to current value and cannot just pass it to InputStreamReader constructor. + // We could use ""by"" implementation, but we can only use ""by"" with interfaces and InputStream is abstract class. +-private val stdin: BufferedReader by lazy { BufferedReader(InputStreamReader(object : InputStream() { ++private val stdin: InputStreamReader by lazy { InputStreamReader(object : InputStream() {","If we're not going to buffer contents, `stdin` wrapper isn't required anymore.",2016-12-28 17:02:10 +780,"@@ -137,6 +137,16 @@ + ) + public String[] scriptResolverEnvironment; + ++ // Javac options ++ @Argument(value = ""-Xuse-javac"", description = ""Use Javac analysis"")","Consider something like `""Use javac for analysis of Java source and class files""`",2017-04-25 08:01:54 +320,"@@ -139,29 +140,34 @@ public fun File.readLines(charset: Charset = Charsets.UTF_8): List { + return result + } + +-/** Creates a buffered reader, or returns self if Reader is already buffered */ ++/** Creates a buffered reader wrapping this Reader, or returns self if Reader is already buffered */","self -> this Reader +",2015-02-11 08:40:01 +319,"@@ -139,29 +140,34 @@ public fun File.readLines(charset: Charset = Charsets.UTF_8): List { + return result + } + +-/** Creates a buffered reader, or returns self if Reader is already buffered */ ++/** Creates a buffered reader wrapping this Reader, or returns self if Reader is already buffered */ + public fun Reader.buffered(bufferSize: Int = defaultBufferSize): BufferedReader + = if (this is BufferedReader) this else BufferedReader(this, bufferSize) + +-/** Creates a buffered writer, or returns self if Writer is already buffered */ ++/** Creates a buffered writer wrapping this Writer, or returns self if Writer is already buffered */","self -> this Writer +",2015-02-11 08:39:52 +355,"@@ -139,4 +139,214 @@ The compiler issues warnings specific to `@Nullable`/`@NotNull` in the following + - a `@Nullable` value is assigned to a not-null location (including passing parameters and receivers to functions/properties); + - a nullable value is assigned to a `@NotNull` location; + - a `@NotNull` value is dereferenced with a safe call (`?.`), used in `!!` or on the left-hand side of an elvis operator `?:`; +- - a `@NotNull` value is compared with `null` through `==`, `!=`, `===` or `!==` +\ No newline at end of file ++ - a `@NotNull` value is compared with `null` through `==`, `!=`, `===` or `!==` ++ ++## More precise type information from annotations ++ ++Goals: ++ - Catch more errors related to nullability in case of Java interop ++ - Keep all class hierarchies consistent at all times (no hierarchy errors related to incorrect annotations) ++ - (!) If the code compiled with annotations, it should always compile without annotations (because external annotations may disappear) ++ ++ This process never results in errors. On any mismatch, a bare platform signature is used (and a warning issued). ++ ++### Annotations recognized by the compiler ++ ++- `org.jetbrains.annotations.Nullable` - value may be null/accepts nulls","Why only the JetBrains versions and not also javax.annotations versions? My own code won't benefit if this is the complete list. +",2015-03-31 16:20:28 +356,"@@ -139,4 +139,214 @@ The compiler issues warnings specific to `@Nullable`/`@NotNull` in the following + - a `@Nullable` value is assigned to a not-null location (including passing parameters and receivers to functions/properties); + - a nullable value is assigned to a `@NotNull` location; + - a `@NotNull` value is dereferenced with a safe call (`?.`), used in `!!` or on the left-hand side of an elvis operator `?:`; +- - a `@NotNull` value is compared with `null` through `==`, `!=`, `===` or `!==` +\ No newline at end of file ++ - a `@NotNull` value is compared with `null` through `==`, `!=`, `===` or `!==` ++ ++## More precise type information from annotations ++ ++Goals: ++ - Catch more errors related to nullability in case of Java interop ++ - Keep all class hierarchies consistent at all times (no hierarchy errors related to incorrect annotations) ++ - (!) If the code compiled with annotations, it should always compile without annotations (because external annotations may disappear) ++ ++ This process never results in errors. On any mismatch, a bare platform signature is used (and a warning issued). ++ ++### Annotations recognized by the compiler ++ ++- `org.jetbrains.annotations.Nullable` - value may be null/accepts nulls ++- `org.jetbrains.annotations.NotNull` - value can not be null/passing null leads to an exception ++- `org.jetbrains.annotations.ReadOnly` - only non-mutating methods can be used on this collection/iterable/iterator ++- `org.jetbrains.annotations.Mutable` - only non-mutating methods can be used on this collection/iterable/iterator","This description seems duplicated? +",2015-03-31 16:20:43 +77,"@@ -139,8 +140,8 @@ public boolean isVar() { + + @NotNull + @Override +- public ValueParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) { +- return new ValueParameterDescriptorImpl(newOwner, index, Lists.newArrayList(getAnnotations()), getName(), getType(), hasDefaultValue, varargElementType); ++ public ValueParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner, @NotNull Name newName) { ++ return new ValueParameterDescriptorImpl(newOwner, index, Lists.newArrayList(getAnnotations()), newName, getType(), declaresDefaultValue(), varargElementType);","I have changed `hasDefaultValue` to `declaresDefaultValue()` - I think that is correct (the constructor parameter is named `declaresDefaultValue`). Besides, `hasDefaultValue` is computed lazily in `hasDefaultValue()` and can be `null` resulting in `NullPointerException` (which, in fact, it does). +",2013-05-27 08:40:03 +322,"@@ -14,48 +14,47 @@ public fun Appendable.appendln(value: CharSequence?): Appendable = append(value) + /** Appends value to the given Appendable and line separator after it. */ + public fun Appendable.appendln(value: Char): Appendable = append(value).append(LINE_SEPARATOR) + +-/** Appends line separator to StringBuilder. */ +- ++/** Appends a line separator to this StringBuilder. */ + public fun StringBuilder.appendln(): StringBuilder = append(LINE_SEPARATOR) + +-/** Appends value to the given StringBuilder and line separator after it. */ ++/** Appends value to this StringBuilder and line separator after it. */","backtickify value, linkify StringBuilder +",2015-02-11 08:44:11 +265,"@@ -14,6 +14,44 @@ public fun File.recurse(block: (File) -> Unit): Unit { + } + + /** ++ * Create an empty directory in the specified directory, using the given prefix and suffix to generate its name. ++ * Prefix shouldn't be shorter than 3 symbols or IllegalArgumentException will be thrown. ++ * ++ * If prefix is not specified then some unspecified name will be used. ++ * If suffix is not specified then "".tmp"" will be used. ++ * If directory is not specified then the default temporary-file directory will be used. ++ * ++ * Returns a file object corresponding to a newly-created directory. ++ * ++ * If some error occurs then IOException is thrown. ++ */ ++public fun createTempDir(prefix: String = ""tmp"", suffix: String? = null, directory: File? = null): File {","I don't really like global functions in stdlib, until absolutely necessary. They pollute global namespace, since they are in the `kotlin` package. Consider creating object to group them into. +",2014-11-26 15:00:40 +879,"@@ -14,7 +14,7 @@ fun elements(): List { + doc { f -> ""Returns `true` if [element] is found in the ${f.collection}."" } + typeParam(""@kotlin.internal.OnlyInputTypes T"") + returns(""Boolean"") +- body(Iterables) { f -> ++ body(Iterables) {","Please extract unrelated changes, such as formatting improvement in a separate PR.",2017-07-03 18:20:49 +380,"@@ -14,88 +14,77 @@ import java.util.Collections // TODO: it's temporary while we have java.util.Col + * Returns an ArrayList of all elements + */ + public fun Array.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun BooleanArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun ByteArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun CharArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun DoubleArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun FloatArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun IntArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun LongArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() + } + + /** + * Returns an ArrayList of all elements + */ + public fun ShortArray.toArrayList(): ArrayList { +- val list = ArrayList(size()) +- for (item in this) list.add(item) +- return list ++ return this.asList().toArrayList() ++} ++ ++/** ++ * Returns an ArrayList of all elements ++ */ ++public fun Collection.toArrayList(): ArrayList { ++ return ArrayList(this) + } + + /** + * Returns an ArrayList of all elements + */ + public fun Iterable.toArrayList(): ArrayList { +- return toCollection(ArrayList(collectionSizeOrDefault(10))) ++ return toCollection(ArrayList())","Still it makes sense to check an actual type of this `Iterable` and switch to `Collection.toArrayList` in case if this is a collection. +",2015-04-27 12:36:49 +909,"@@ -141,13 +141,28 @@ public static void checkAnnotationType( + } + } + ++ @Nullable ++ private static T findAncestorOfType(@NotNull PsiElement element, Class ancestorType) {","There is already `getParentOfType`, please use it here",2017-07-18 11:47:13 +256,"@@ -141,6 +183,64 @@ public open class KotlinCompile(): AbstractCompile() { + } + } + ++public open class Kotlin2JsCompile(): AbstractKotlinCompile() { ++ override val compiler = K2JSCompiler() ++ ++ override fun createBlankArgs(): K2JSCompilerArguments = K2JSCompilerArguments() ++ ++ public fun addLibraryFiles(vararg fs: String) { ++ kotlinOptions.libraryFiles = (kotlinOptions.libraryFiles + fs).copyToArray() ++ } ++ ++ public fun addLibraryFiles(vararg fs: File) { ++ val strs = fs.map{it.getPath()}.copyToArray() ++ addLibraryFiles(*strs) ++ } ++ ++ fun outputFile(): String { ++ return if (StringUtils.isEmpty(kotlinOptions.outputFile)) { ++ ""${kotlinDestinationDir}/app.js""","I think outputFile can not be omitted and if it omitted compilation should be failed. +",2014-11-11 18:19:53 +257,"@@ -141,6 +183,64 @@ public open class KotlinCompile(): AbstractCompile() { + } + } + ++public open class Kotlin2JsCompile(): AbstractKotlinCompile() { ++ override val compiler = K2JSCompiler() ++ ++ override fun createBlankArgs(): K2JSCompilerArguments = K2JSCompilerArguments() ++ ++ public fun addLibraryFiles(vararg fs: String) { ++ kotlinOptions.libraryFiles = (kotlinOptions.libraryFiles + fs).copyToArray() ++ } ++ ++ public fun addLibraryFiles(vararg fs: File) { ++ val strs = fs.map{it.getPath()}.copyToArray() ++ addLibraryFiles(*strs) ++ } ++ ++ fun outputFile(): String { ++ return if (StringUtils.isEmpty(kotlinOptions.outputFile)) { ++ ""${kotlinDestinationDir}/app.js"" ++ } else { ++ kotlinOptions.outputFile ++ } ++ } ++ ++ public fun sourceMapDestinationDir(): File = File(outputFile()).directory ++ ++ { ++ getOutputs().file(MethodClosure(this, ""outputFile"")) ++ } ++ ++ override fun populateTargetSpecificArgs(args: K2JSCompilerArguments, sources: ArrayList) { ++ args.outputFile = outputFile() ++ args.outputPrefix = kotlinOptions.outputPrefix ++ args.outputPostfix = kotlinOptions.outputPostfix ++ args.libraryFiles = kotlinOptions.libraryFiles ++ args.target = kotlinOptions.target ++ args.sourceMap = kotlinOptions.sourceMap ++ ++ val outputDir = File(args.outputFile).directory ++ if (!outputDir.exists()) { ++ if (!outputDir.mkdirs()) { ++ throw GradleException(""Failed to create output directory ${outputDir} or one of its ancestors"") ++ } ++ } ++ } ++} ++ ++public open class RewritePathsInSourceMap(): DefaultTask() { ++ var sourceMapPath: () -> String = {""""} ++ var sourceRootDir: () -> String = {""""} ++ ++ [TaskAction] fun rewrite() { ++ val file = File(sourceMapPath()) ++ val text = file.readText(""UTF-8"")","charset parameter may be omitted -- UTF-8 will by use by default +",2014-11-11 18:26:21 +260,"@@ -141,7 +185,63 @@ public open class KotlinCompile(): AbstractCompile() { + } + } + +-public open class KDoc(): SourceTask() { ++public open class Kotlin2JsCompile() : AbstractKotlinCompile() { ++ override val compiler = K2JSCompiler() ++ ++ override fun createBlankArgs(): K2JSCompilerArguments = K2JSCompilerArguments() ++ ++ public fun addLibraryFiles(vararg fs: String) {","I think we should extract all libraries from dependencies instead. +",2014-11-12 13:22:09 +259,"@@ -141,7 +185,63 @@ public open class KotlinCompile(): AbstractCompile() { + } + } + +-public open class KDoc(): SourceTask() { ++public open class Kotlin2JsCompile() : AbstractKotlinCompile() { ++ override val compiler = K2JSCompiler() ++ ++ override fun createBlankArgs(): K2JSCompilerArguments = K2JSCompilerArguments() ++ ++ public fun addLibraryFiles(vararg fs: String) { ++ kotlinOptions.libraryFiles = (kotlinOptions.libraryFiles + fs).copyToArray() ++ } ++ ++ public fun addLibraryFiles(vararg fs: File) { ++ val strs = fs.map { it.getPath() }.copyToArray() ++ addLibraryFiles(*strs) ++ } ++ ++ fun outputFile(): String? = kotlinOptions.outputFile ++ ++ public fun sourceMapDestinationDir(): File = File(outputFile()).directory ++ ++ { ++ getOutputs().file(MethodClosure(this, ""outputFile"")) ++ } ++ ++ override fun populateTargetSpecificArgs(args: K2JSCompilerArguments) { ++ args.outputFile = outputFile() ++ args.outputPrefix = kotlinOptions.outputPrefix ++ args.outputPostfix = kotlinOptions.outputPostfix ++ args.libraryFiles = kotlinOptions.libraryFiles ++ args.target = kotlinOptions.target ++ args.sourceMap = kotlinOptions.sourceMap ++ ++ if (args.outputFile == null) { ++ throw GradleException(""${getName()}.kotlinOptions.outputFile must be set to a string."") ++ } ++ ++ val outputDir = File(args.outputFile).directory ++ if (!outputDir.exists()) { ++ if (!outputDir.mkdirs()) { ++ throw GradleException(""Failed to create output directory ${outputDir} or one of its ancestors"") ++ } ++ } ++ } ++} ++ ++public open class RewritePathsInSourceMap() : DefaultTask() {","Ideally it should be fixed in compiler as part of [KT-4078](https://youtrack.jetbrains.com/issue/KT-4078). You can just add TODO comment that this hack should be dropped after KT-4078 will be fixed or fix it :) +",2014-11-12 13:18:02 +303,"@@ -142,7 +176,7 @@ public inline fun > Map.mapKeysTo(destinatio + } + + /** +- * Puts all the entries into this [[MutableMap]] with the first value in the pair being the key and the second the value ++ * Puts all the entries into this [MutableMap] with the first value in the pair being the key and the second the value","""Puts given values"", and again value vs component for Pair. +",2015-02-09 16:06:41 +760,"@@ -144,8 +146,14 @@ fun createKeywordConstructLookupElement( + val beforeCaret = tailBeforeCaret.indentLinesAfterFirst(newIndent) + val afterCaret = tailAfterCaret.indentLinesAfterFirst(newIndent) + +- insertionContext.document.insertString(offset, beforeCaret + afterCaret) +- insertionContext.editor.moveCaret(offset + beforeCaret.length) ++ val element = insertionContext.file.findElementAt(offset)?.getNextSiblingIgnoringWhitespaceAndComments(true)","Why getNextSiblingIgnoringWhitespaceAndComments() is needed? I expect that it is for 'for' keyword completion, but at least one test needed for it. +I also think that there shouldn't be comments skipping.",2017-04-11 16:21:06 +761,"@@ -144,8 +146,14 @@ fun createKeywordConstructLookupElement( + val beforeCaret = tailBeforeCaret.indentLinesAfterFirst(newIndent) + val afterCaret = tailAfterCaret.indentLinesAfterFirst(newIndent) + +- insertionContext.document.insertString(offset, beforeCaret + afterCaret) +- insertionContext.editor.moveCaret(offset + beforeCaret.length) ++ val element = insertionContext.file.findElementAt(offset)?.getNextSiblingIgnoringWhitespaceAndComments(true) ++ ++ if (element != null && beforeCaret.trimStart().startsWith(insertionContext.document.getText(TextRange.from(element.startOffset, 1)))) {",I think it will be more safe to use == instead of startsWith(),2017-04-11 16:23:32 +0,"@@ -145,10 +145,22 @@ private static JetElement overrideFunction(Project project, JetFile file, Simple + StringBuilder bodyBuilder = new StringBuilder(""override fun ""); + bodyBuilder.append(descriptor.getName()); + bodyBuilder.append(""(""); ++ boolean isAbstractFun = descriptor.getModality() == Modality.ABSTRACT; ++ StringBuilder delegationBuilder = new StringBuilder();","It's not very critical now, but I think that your decision to barter flat and simple structure of this method to one more iteration over parameters collection was a bad deal. Now it's really difficult to understand the logic of filling StringBuilder variables. +",2012-04-03 12:21:38 +725,"@@ -15,6 +15,7 @@ public abstract class Mine : java.util.AbstractList { + public open /*fake_override*/ fun clear(): kotlin.Unit + public open /*fake_override*/ fun contains(/*0*/ T!): kotlin.Boolean + public open /*fake_override*/ fun containsAll(/*0*/ kotlin.collections.Collection): kotlin.Boolean ++ public open /*fake_override*/ fun forEach(/*0*/ java.util.function.Consumer!): kotlin.Unit","You'd better not to change existing tests, but to create a new test group with the same test data and your flag enabled.",2017-04-05 15:27:24 +304,"@@ -151,7 +185,7 @@ public fun MutableMap.putAll(vararg values: Pair): Unit { + } + + /** +- * Puts all the entries into this [[MutableMap]] with the first value in the pair being the key and the second the value ++ * Puts all the entries into this [MutableMap] with the first value in the pair being the key and the second the value","""Puts elements of the given collection"" +",2015-02-09 16:07:10 +618,"@@ -152,13 +152,14 @@ class ClassBodyConverter(private val psiClass: PsiClass, + ): Member? { + when (member) { + is PsiMethod -> { +- memberToPropertyInfo[member]?.let { propertyInfo -> +- if (propertyInfo.field != null) return null // just drop the method, property will be generated when converting the field +- return if (member == propertyInfo.getMethod || propertyInfo.getMethod == null) +- converter.convertProperty(propertyInfo, classKind) +- else +- null // drop the method, property will be generated when converting the field or the getter +- } ++ if (!member.hasModifierProperty(PsiModifier.NATIVE))","This doesn't seem to be a correct check. This is valid Kotlin: + +``` kotlin +val foo: Int = 0 + external get +``` +",2016-09-22 10:50:26 +568,"@@ -1520,6 +1520,15 @@ + language=""kotlin"" + /> + ++ + ++ diagnosticFactory ++ ) { ++ // If is not a property, then it must have no modifier ++ if (parameter.getValOrVarNode() == null) { ++ checkParameterHasNoModifier(trace, parameter, diagnosticFactory); ++ } ++ } ++ ++ public static void checkParameterHasNoModifier( ++ @NotNull BindingTrace trace, ++ @NotNull JetParameter parameter, ++ @NotNull DiagnosticFactory1 diagnosticFactory ++ ) { ++ JetModifierList modifiers = parameter.getModifierList(); ++ if (modifiers != null) { ++ ASTNode node = modifiers.getNode().getFirstChildNode(); ++ ++ while (node != null) { ++ IElementType elementType = node.getElementType(); ++ ++ if (elementType != JetTokens.VARARG_KEYWORD && elementType instanceof JetKeywordToken) { ++ trace.report(diagnosticFactory.on(node.getPsi(), (JetKeywordToken) elementType)); ++ break;","fun foo(public abstract x: Int) //abstract should also highlighted as error +",2013-08-29 10:12:30 +348,"@@ -158,6 +157,7 @@ protected void blackBox() { + Method method = aClass.getMethod(""box""); + String r = (String) method.invoke(null); + assertEquals(""OK"", r); ++ System.out.println(generateToText());","I beleive this was commited erroneously. +",2015-03-26 15:35:44 +284,"@@ -16,10 +16,25 @@ + + package kotlin + ++/** ++ * Represents a sequence of numbers or characters with a given start value, end value and step. ++ * This class is intended to be used in 'for' loops, and the JVM backend suggests efficient ++ * bytecode generation for it. Progressions with a step of -1 can be created through the ++ * `downTo` method on classes representing primitive types.","Link to `downTo` method. +",2015-02-09 15:42:22 +285,"@@ -16,10 +16,25 @@ + + package kotlin + ++/** ++ * Represents a sequence of numbers or characters with a given start value, end value and step. ++ * This class is intended to be used in 'for' loops, and the JVM backend suggests efficient ++ * bytecode generation for it. Progressions with a step of -1 can be created through the ++ * `downTo` method on classes representing primitive types. ++ */ + public trait Progression : Iterable { ++ /** ++ * The start value of a progression. ++ */ + public val start: N + ++ /** ++ * The end value of the progression (inclusive).","start ""a progression"", end ""the progression"" +",2015-02-09 15:42:45 +269,"@@ -16,10 +16,25 @@ + + package kotlin + ++/** ++ * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass. ++ */ + public open class Any { ++ /** ++ * Indicates whether some other object is ""equal to"" this one. Implementations must follow ++ * the same contract as the [Java equals() method](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29).","Referencing Java in such a way doesn't make it look like a standard library for a _language_, which is targeting different platforms. E.g. for JS it may be different contract. +",2015-02-09 15:23:56 +270,"@@ -16,10 +16,25 @@ + + package kotlin + ++/** ++ * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass. ++ */ + public open class Any { ++ /** ++ * Indicates whether some other object is ""equal to"" this one. Implementations must follow ++ * the same contract as the [Java equals() method](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29). ++ * Note that the `==` operator in Kotlin code is translated into a null-safe call to [equals].","Expand ""null-safe call"". I would read it as ""a?.equals(b)"" which is wrong, because expression type for `==` is `Boolean`, not `Boolean?` +",2015-02-09 15:24:55 +271,"@@ -16,10 +16,25 @@ + + package kotlin + ++/** ++ * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass. ++ */ + public open class Any { ++ /** ++ * Indicates whether some other object is ""equal to"" this one. Implementations must follow ++ * the same contract as the [Java equals() method](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29). ++ * Note that the `==` operator in Kotlin code is translated into a null-safe call to [equals]. ++ */ + public open fun equals(other: Any?): Boolean + ++ /** ++ * Returns a hash code value for the object. Implementations must follow the same contract ++ * as the [Java hashCode() method](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29).","Same note about Java-ism. +",2015-02-09 15:25:14 +281,"@@ -16,10 +16,30 @@ + + package kotlin + ++/** ++ * Marks the annotated class as a data class. Data classes have automatically generated","""When processing data class, compiler will generate""... +",2015-02-09 15:39:18 +169,"@@ -16,11 +16,17 @@ + + package org.jetbrains.jet.plugin.refactoring.rename; + +-import org.jetbrains.jet.JetTestUtils; +-import org.jetbrains.jet.test.TestMetadata; ++import junit.framework.Assert; ++import junit.framework.Test; ++import junit.framework.TestSuite; + + import java.io.File; + import java.util.regex.Pattern; ++import org.jetbrains.jet.JetTestUtils; ++import org.jetbrains.jet.test.InnerTestClasses; ++import org.jetbrains.jet.test.TestMetadata; ++ ++import org.jetbrains.jet.plugin.refactoring.rename.AbstractRenameTest;","Changes in this file shouldn't have been included in your pull request +",2014-04-09 16:13:35 +279,"@@ -16,13 +16,31 @@ + + package kotlin + ++/** ++ * Returns true if the receiver and the [other] object are the same object instance, or if they ++ * are both null. ++ */ + public fun Any?.identityEquals(other: Any?): Boolean // = this === other + ++/** ++ * Returns true if the receiver and the [other] object are ""equal"" to each other, or if they are","Link to Any.equals() on ""equal"" would be good, to refer to explanation of equality. +",2015-02-09 15:37:06 +272,"@@ -16,13 +16,44 @@ + + package kotlin + ++/** ++ * Represents an array (specifically, a Java array when targeting the JVM platform). ++ * Array instances can be created using the [array] and [arrayOfNulls] standard ++ * library functions. ++ * See [Kotlin language documentation](http://kotlinlang.org/docs/reference/basic-types.html#arrays) ++ * for more information on arrays. ++ */ + public class Array private (): Cloneable { ++ /** ++ * Returns the array element at the specified [index]. This method can be called using the ++ * brackets notation:","We usually call it ""index operator"", I think, not ""brackets notation"". +",2015-02-09 15:26:26 +273,"@@ -16,13 +16,44 @@ + + package kotlin + ++/** ++ * Represents an array (specifically, a Java array when targeting the JVM platform). ++ * Array instances can be created using the [array] and [arrayOfNulls] standard ++ * library functions. ++ * See [Kotlin language documentation](http://kotlinlang.org/docs/reference/basic-types.html#arrays) ++ * for more information on arrays. ++ */ + public class Array private (): Cloneable { ++ /** ++ * Returns the array element at the specified [index]. This method can be called using the ++ * brackets notation: ++ * ``` ++ * val = arr[index]","bad example, ""val"" is keyword. +",2015-02-09 15:27:02 +274,"@@ -16,13 +16,44 @@ + + package kotlin + ++/** ++ * Represents an array (specifically, a Java array when targeting the JVM platform). ++ * Array instances can be created using the [array] and [arrayOfNulls] standard ++ * library functions. ++ * See [Kotlin language documentation](http://kotlinlang.org/docs/reference/basic-types.html#arrays) ++ * for more information on arrays. ++ */ + public class Array private (): Cloneable { ++ /** ++ * Returns the array element at the specified [index]. This method can be called using the ++ * brackets notation: ++ * ``` ++ * val = arr[index] ++ * ``` ++ */ + public fun get(index: Int): T ++ ++ /** ++ * Sets the array element at the specified [index] to the specified [value]. This method can ++ * be called using the brackets notation: ++ * ``` ++ * arr[index] = val","Same here for ""brackets"" and ""val"" +",2015-02-09 15:27:25 +275,"@@ -16,13 +16,44 @@ + + package kotlin + ++/** ++ * Represents an array (specifically, a Java array when targeting the JVM platform). ++ * Array instances can be created using the [array] and [arrayOfNulls] standard ++ * library functions. ++ * See [Kotlin language documentation](http://kotlinlang.org/docs/reference/basic-types.html#arrays) ++ * for more information on arrays. ++ */ + public class Array private (): Cloneable { ++ /** ++ * Returns the array element at the specified [index]. This method can be called using the ++ * brackets notation: ++ * ``` ++ * val = arr[index] ++ * ``` ++ */ + public fun get(index: Int): T ++ ++ /** ++ * Sets the array element at the specified [index] to the specified [value]. This method can ++ * be called using the brackets notation: ++ * ``` ++ * arr[index] = val ++ * ``` ++ */ + public fun set(index: Int, value: T): Unit + ++ /** ++ * Returns the length of the array.","""Returns number of elements in the array"". Method called ""size"" shouldn't be described with word ""length"" +",2015-02-09 15:27:58 +484,"@@ -16,14 +16,9 @@ + + package org.jetbrains.kotlin.resolve.descriptorUtil + +-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + import org.jetbrains.kotlin.descriptors.annotations.Annotated + import org.jetbrains.kotlin.name.FqName + +-private val HIDDEN_ANNOTATION_FQ_NAME = FqName(""kotlin.HiddenDeclaration"") +- +-public fun DeclarationDescriptor.isAnnotatedAsHidden(): Boolean = annotations.findAnnotation(HIDDEN_ANNOTATION_FQ_NAME) != null +- + private val NO_INFER_ANNOTATION_FQ_NAME = FqName(""kotlin.NoInfer"")","I think this whole file should be moved to `frontend`... +",2015-10-10 20:45:40 +918,"@@ -16,18 +16,25 @@ + + package kotlin.script.templates.standard + ++// discuss ++// ++// These are some 'basic' script templates ++// Should we keep them here?","I think we should do the following with these: +* `SimpleScriptTemplate` -> remove (script with args can be always used instead of it) +* `kotlin.script.templates.standard.ScriptTemplateWithArgs` -> rename and move to `kotlin.script.templates.StandardScriptTemplate` +* `kotlin.script.templates.standard.ScriptTemplateWithBindings` -> move to `kotlin.script.templates.ScriptTemplateWithBindings`",2017-07-25 10:25:34 +276,"@@ -16,26 +16,66 @@ + + package kotlin + ++/** ++ * An iterator over a collection. Allows to sequentially access the elements in a collection.","Not necessary ""in a collection"". +",2015-02-09 15:28:42 +277,"@@ -16,26 +16,66 @@ + + package kotlin + ++/** ++ * An iterator over a collection. Allows to sequentially access the elements in a collection. ++ */ + public trait Iterator { ++ /** ++ * Returns the next element in the iteration. ++ */ + public fun next(): T ++ ++ /** ++ * Returns `true` if the iteration has more elements. ++ */ + public fun hasNext(): Boolean + } + ++/** ++ * An iterator over a mutable collection. Provides the ability to remove elements while iterating. ++ * @see MutableCollection.iterator ++ */ + public trait MutableIterator : Iterator { ++ /** ++ * Removes from the underlying collection the last element returned by this iterator. ++ */ + public fun remove(): Unit + } + ++/** ++ * An iterator over a collection that supports indexed access. ++ * @see List.listIterator ++ */ + public trait ListIterator : Iterator { + // Query Operations + override fun next(): T","Do we need overrides here? +",2015-02-09 15:34:07 +642,"@@ -16,29 +16,26 @@ + + package org.jetbrains.kotlin.idea.codeInsight.surroundWith + +-import com.intellij.openapi.project.Project + import com.intellij.psi.PsiElement + import com.intellij.psi.PsiReference + import com.intellij.psi.search.LocalSearchScope + import com.intellij.psi.search.SearchScope + import com.intellij.psi.search.searches.ReferencesSearch + import com.intellij.psi.util.PsiUtilCore +-import org.jetbrains.kotlin.descriptors.VariableDescriptor +-import org.jetbrains.kotlin.idea.caches.resolve.* ++import org.jetbrains.kotlin.idea.caches.resolve.analyze + import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils +-import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers + import org.jetbrains.kotlin.idea.core.ShortenReferences ++import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers + import org.jetbrains.kotlin.psi.* + import org.jetbrains.kotlin.resolve.BindingContext + import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode + import org.jetbrains.kotlin.types.KotlinType +- +-import java.util.ArrayList ++import java.util.* + + object MoveDeclarationsOutHelper {","This `object` serves no purpose; the contents of the file should simply be top-level functions +",2016-10-18 18:44:48 +324,"@@ -16,40 +16,112 @@ + + package kotlin + ++/** ++ * Classes that inherit from this trait can be represented as a sequence of elements that can ++ * be iterated over. ++ */ + public trait Iterable {","doc for `T`? +",2015-03-02 17:23:35 +920,"@@ -16,6 +16,11 @@ + + package kotlin.script.extensions + ++// discuss ++ ++// Is this an appropriate place to put this class?","This doesn't look like an appropriate place. If I understand correctly, it has nothing to do with scripts, so putting it into package `kotlin.script.extensions` is risky. As soon as we decide to publish it as a supported compiler plugin, we'll have to move it to another package and artifact, causing incompatibilities, so maybe it'd be better to do this earlier.",2017-07-25 11:06:18 +282,"@@ -16,8 +16,18 @@ + + package kotlin + ++/** ++ * Annotates the parameter of a function annotates as [inline] and forbids inlining of","Typo: ""annotates as [inline]"" -> ""annotated as [inline]"" +",2015-02-09 15:40:41 +283,"@@ -16,8 +16,18 @@ + + package kotlin + ++/** ++ * Annotates the parameter of a function annotates as [inline] and forbids inlining of ++ * function literals passed as arguments for this parameter. ++ */ + public annotation class noinline + ++/**","Add cross-reference to other annotations, like `noinline` +",2015-02-09 15:41:44 +778,"@@ -161,6 +162,13 @@ object KotlinToJVMBytecodeCompiler { + ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() + writeOutput(state.configuration, state.factory, null) + } ++ ++ if (chunk.size == 1 && projectConfiguration.getBoolean(JVMConfigurationKeys.USE_JAVAC)) {","If the chunk contains multiple modules and `-Xuse-javac` has been specified, maybe we should report a warning saying that we won't in fact use javac for compilation",2017-04-25 07:54:52 +762,"@@ -161,6 +162,14 @@ object KotlinToJVMBytecodeCompiler { + ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() + writeOutput(state.configuration, state.factory, null) + } ++ ++ if (chunk.size == 1) { ++ val javacWrapper = JavacWrapper.getInstance(environment.project) ++ if (projectConfiguration[JVMConfigurationKeys.USE_JAVAC]!!) {",@baratynskiy Please use `getBoolean(...)` instead of `get(...)!!`,2017-04-12 15:41:33 +76,"@@ -162,4 +162,8 @@ change.function.signature.family=Change function signature + change.function.signature.chooser.title=Choose signature + change.function.signature.action=Change function signature + remove.unnecessary.parentheses=Remove unnecessary parentheses +-remove.unnecessary.parentheses.family=Remove Unnecessary Parentheses +\ No newline at end of file ++remove.unnecessary.parentheses.family=Remove Unnecessary Parentheses ++add.function.to.supertype.family=Add Function to Supertype","While I know it's technically not 100% correct and maybe ""Add Function to _Superclassifier_"" would be a more accurate name for this quickfix I still want to stick with the name ""Add Function to Supertype"". In my opinion the user would be confused by using word ""superclassifier"". I can change the name though if you disagree. +",2013-05-16 07:45:39 +288,"@@ -1629,70 +1629,70 @@ public fun Stream.lastIndexOf(element: T): Int { + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun Array.lastOrNull(): T? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun BooleanArray.lastOrNull(): Boolean? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun ByteArray.lastOrNull(): Byte? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun CharArray.lastOrNull(): Char? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun DoubleArray.lastOrNull(): Double? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun FloatArray.lastOrNull(): Float? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun IntArray.lastOrNull(): Int? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty + */ + public fun LongArray.lastOrNull(): Long? { + return if (isEmpty()) null else this[size() - 1] + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last element, or null if the collection is empty","Back-tick quote ""null""? +",2015-02-09 15:48:24 +503,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl {","It seems more like just ""createIncrementalCache"" +",2016-02-02 15:30:24 +502,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl { ++ val cacheDir = File(cachesBaseDir, ""increCache.${target.name}"") ++ cacheDir.mkdirs() ++ return GradleIncrementalCacheImpl(targetDataRoot = cacheDir, targetOutputDir = outputDir, target = target) ++ } ++ ++ fun getIncrementalCache(it: TargetId) = caches.getOrPut(it, { getOrCreateIncrementalCache(it) }) ++ ++ fun PsiClass.findLookupSymbols(): Iterable { ++ val fqn = qualifiedName.orEmpty() ++ return listOf(LookupSymbol(name.orEmpty(), if (fqn == name) """" else fqn.removeSuffix(""."" + name!!))) + ++ methods.map { LookupSymbol(it.name, fqn) } + ++ fields.map { LookupSymbol(it.name.orEmpty(), fqn) } + ++ innerClasses.flatMap { it.findLookupSymbols() } ++ } ++ ++ fun Iterable.files(filesFilter: (File) -> Boolean = { true }, logAction: (LookupSymbol, Iterable) -> Unit = { l,fs -> }): Iterable =","1. Formatting is unusual to our codebase (surrounding ""->"" with spaces). +2. logAction is the same for both call-sites +3. filesFiler is almost the same for call-sites. Could be replaced with excludedFiles: Set +",2016-02-02 15:25:33 +504,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl { ++ val cacheDir = File(cachesBaseDir, ""increCache.${target.name}"") ++ cacheDir.mkdirs() ++ return GradleIncrementalCacheImpl(targetDataRoot = cacheDir, targetOutputDir = outputDir, target = target) ++ } ++ ++ fun getIncrementalCache(it: TargetId) = caches.getOrPut(it, { getOrCreateIncrementalCache(it) }) ++ ++ fun PsiClass.findLookupSymbols(): Iterable { ++ val fqn = qualifiedName.orEmpty() ++ return listOf(LookupSymbol(name.orEmpty(), if (fqn == name) """" else fqn.removeSuffix(""."" + name!!))) + ++ methods.map { LookupSymbol(it.name, fqn) } + ++ fields.map { LookupSymbol(it.name.orEmpty(), fqn) } + ++ innerClasses.flatMap { it.findLookupSymbols() } ++ } ++ ++ fun Iterable.files(filesFilter: (File) -> Boolean = { true }, logAction: (LookupSymbol, Iterable) -> Unit = { l,fs -> }): Iterable = ++ flatMap { lookup -> ++ val files = lookupStorage.get(lookup).map(::File).filter(filesFilter) ++ if (files.any()) { ++ logAction(lookup, files) ++ } ++ files ++ } ++ ++ fun dirtyLookupSymbolsFromRemovedKotlinFiles(): List {","I don't think these lookups can useful: +- for JPS a processing of removed classes is done in `clearCacheForRemovedClasses`; that method uses proto from caches for dirty fqnames; +- current implementation can only return lookups of classes. + +So I suggest to remove this function. +",2016-02-02 17:58:19 +505,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl { ++ val cacheDir = File(cachesBaseDir, ""increCache.${target.name}"") ++ cacheDir.mkdirs() ++ return GradleIncrementalCacheImpl(targetDataRoot = cacheDir, targetOutputDir = outputDir, target = target) ++ } ++ ++ fun getIncrementalCache(it: TargetId) = caches.getOrPut(it, { getOrCreateIncrementalCache(it) }) ++ ++ fun PsiClass.findLookupSymbols(): Iterable { ++ val fqn = qualifiedName.orEmpty() ++ return listOf(LookupSymbol(name.orEmpty(), if (fqn == name) """" else fqn.removeSuffix(""."" + name!!))) + ++ methods.map { LookupSymbol(it.name, fqn) } + ++ fields.map { LookupSymbol(it.name.orEmpty(), fqn) } + ++ innerClasses.flatMap { it.findLookupSymbols() } ++ } ++ ++ fun Iterable.files(filesFilter: (File) -> Boolean = { true }, logAction: (LookupSymbol, Iterable) -> Unit = { l,fs -> }): Iterable = ++ flatMap { lookup -> ++ val files = lookupStorage.get(lookup).map(::File).filter(filesFilter) ++ if (files.any()) { ++ logAction(lookup, files) ++ } ++ files ++ } ++ ++ fun dirtyLookupSymbolsFromRemovedKotlinFiles(): List { ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ return if (removedKotlinFiles.isNotEmpty()) ++ targets.flatMap { getIncrementalCache(it).classesBySources(removedKotlinFiles).map { LookupSymbol(it.fqNameForClassNameWithoutDollars.shortName().toString(), it.packageFqName.toString()) } } ++ else listOf() ++ } ++ ++ fun dirtyLookupSymbolsFromModifiedJavaFiles(): List { ++ val modifiedJavaFiles = modified.filter { it.isJavaFile() } ++ return (if (modifiedJavaFiles.any()) { ++ val rootDisposable = Disposer.newDisposable() ++ val configuration = CompilerConfiguration() ++ val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) ++ val project = environment.project ++ val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl ++ modifiedJavaFiles.flatMap { ++ val javaFile = psiFileFactory.createFileFromText(it.nameWithoutExtension, Language.findLanguageByID(""JAVA"")!!, it.readText()) ++ if (javaFile is PsiJavaFile) ++ javaFile.classes.flatMap { it.findLookupSymbols() } ++ else listOf() ++ } ++ } else listOf()) ++ } ++ ++ fun dirtyKotlinSourcesFromGradle(): List { ++ // TODO: handle classpath changes similarly - compare with cashed version (likely a big change, may be costly, some heuristics could be considered) ++ val modifiedKotlinFiles = modified.filter { it.isKotlinFile() } ++ val lookupSymbols = ++ dirtyLookupSymbolsFromModifiedJavaFiles() + ++ dirtyLookupSymbolsFromRemovedKotlinFiles() ++ // TODO: add dirty lookups from modified kotlin files to reduce number of steps needed ++ ++ if (lookupSymbols.any()) { ++ val kotlinModifiedFilesSet = modifiedKotlinFiles.toHashSet() ++ return modifiedKotlinFiles + ++ lookupSymbols.files( ++ filesFilter = { it !in kotlinModifiedFilesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ } ++ return modifiedKotlinFiles ++ } ++ ++ fun isClassPathChanged(): Boolean { ++ // TODO: that doesn't look to wise - join it first and then split here, consider storing it somewhere in between ++ val classpath = args.classpath.split(File.pathSeparator).map { File(it) }.toHashSet() ++ val changedClasspath = modified.filter { classpath.contains(it) } ++ return changedClasspath.any() ++ } ++ ++ fun allCachesVersions() = allCachesVersions(cachesBaseDir, listOf(cachesBaseDir)) ++ ++ fun calculateSourcesToCompile(): Pair, Boolean> { ++ ++ if (!experimentalIncremental || ++ !isIncrementalRequested || ++ // TODO: more precise will be not to rebuild unconditionally on classpath changes, but retrieve lookup info and try to find out which sources are affected by cp changes ++ isClassPathChanged() || ++ // so far considering it not incremental TODO: store java files in the cache and extract removed symbols from it here ++ removed.any { it.isJavaFile() } ++ ) { ++ logger.kotlinInfo(if (!isIncrementalRequested) ""clean caches on rebuild"" else ""classpath changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ val actions = if (isIncrementalRequested) allCachesVersions().map { it.checkVersion() } ++ else listOf(CacheVersion.Action.REBUILD_ALL_KOTLIN) ++ // TODO: find out whether these flags should be emulated too ++// val hasKotlin = HasKotlinMarker(dataManager) ++// val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager) ++ ++ for (status in actions.distinct().sorted()) { ++ when (status) { ++ CacheVersion.Action.REBUILD_ALL_KOTLIN -> { ++ logger.kotlinInfo(""Kotlin global lookup map format changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ CacheVersion.Action.REBUILD_CHUNK -> { ++ logger.kotlinInfo(""Clearing caches for "" + targets.joinToString { it.name }) ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_NORMAL_CACHES -> { ++ logger.kotlinInfo(""Clearing caches for all targets"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_EXPERIMENTAL_CACHES -> { ++ logger.kotlinInfo(""Clearing experimental caches for all targets"") ++ targets.forEach { getIncrementalCache(it).cleanExperimental() } ++ } ++ CacheVersion.Action.CLEAN_DATA_CONTAINER -> { ++ logger.kotlinInfo(""Clearing lookup cache"") ++ lookupStorage.clean() ++ dataContainerCacheVersion(cachesBaseDir).clean() ++ } ++ else -> { ++ assert(status == CacheVersion.Action.DO_NOTHING) { ""Unknown version status $status"" } ++ } ++ } ++ } ++ val dirtyFiles = dirtyKotlinSourcesFromGradle().distinct() ++ // first dirty files should be found and only then caches cleared ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ targets.forEach { getIncrementalCache(it).let { ++ it.markOutputClassesDirty(removedKotlinFiles) ++ it.removeClassfilesBySources(removedKotlinFiles) ++ }} ++ return Pair(dirtyFiles, true) ++ } ++ ++ fun cleanupOnError() { ++ val outputDirFile = File(args.destination!!) ++ ++ assert(outputDirFile.exists()) ++ val generatedRelPaths = allGeneratedFiles.map { it.outputFile.toRelativeString(outputDirFile) } ++ logger.kotlinInfo(""deleting output on error: ${generatedRelPaths.joinToString()}"") ++ ++ allGeneratedFiles.forEach { it.outputFile.delete() } ++ generatedRelPaths.forEach { File(destinationDir, it).delete() } ++ } ++ ++ fun processCompilerExitCode(exitCode: ExitCode) { ++ if (exitCode != ExitCode.OK) { ++ cleanupOnError() ++ } ++ when (exitCode) { ++ ExitCode.COMPILATION_ERROR -> throw GradleException(""Compilation error. See log for more details"") ++ ExitCode.INTERNAL_ERROR -> throw GradleException(""Internal compiler error. See log for more details"") ++ ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException(""Script execution error. See log for more details"") ++ ExitCode.OK -> logger.kotlinInfo(""Compilation succeeded"") ++ } ++ } ++ ++ fun outputRelativePath(f: File) = f.toRelativeString(outputDir) ++ ++ ++ if (!experimentalIncremental) { ++ anyClassesCompiled = true ++ processCompilerExitCode(compileNotIncremental(sources, outputDir, args)) ++ return ++ } ++ logger.warn(""Using experimental kotlin incremental compilation"") ++ ++ anyClassesCompiled = false ++ ++ // TODO: decide what to do if no files are considered dirty - rebuild or skip the module ++ var (sourcesToCompile, isIncrementalDecided) = calculateSourcesToCompile() ++ ++ if (isIncrementalDecided) { ++ // TODO: process as list here, merge into string later ++ args.classpath = args.classpath + File.pathSeparator + outputDir.absolutePath ++ } ++ ++ while (sourcesToCompile.any()) { ++ logger.kotlinInfo(""compile iteration: ${sourcesToCompile.joinToString{ projectRelativePath(it) }}"") ++ ++ val (exitCode, generatedFiles) = compileChanged(","What's the point in using named arguments here? +",2016-02-02 18:10:10 +506,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl { ++ val cacheDir = File(cachesBaseDir, ""increCache.${target.name}"") ++ cacheDir.mkdirs() ++ return GradleIncrementalCacheImpl(targetDataRoot = cacheDir, targetOutputDir = outputDir, target = target) ++ } ++ ++ fun getIncrementalCache(it: TargetId) = caches.getOrPut(it, { getOrCreateIncrementalCache(it) }) ++ ++ fun PsiClass.findLookupSymbols(): Iterable { ++ val fqn = qualifiedName.orEmpty() ++ return listOf(LookupSymbol(name.orEmpty(), if (fqn == name) """" else fqn.removeSuffix(""."" + name!!))) + ++ methods.map { LookupSymbol(it.name, fqn) } + ++ fields.map { LookupSymbol(it.name.orEmpty(), fqn) } + ++ innerClasses.flatMap { it.findLookupSymbols() } ++ } ++ ++ fun Iterable.files(filesFilter: (File) -> Boolean = { true }, logAction: (LookupSymbol, Iterable) -> Unit = { l,fs -> }): Iterable = ++ flatMap { lookup -> ++ val files = lookupStorage.get(lookup).map(::File).filter(filesFilter) ++ if (files.any()) { ++ logAction(lookup, files) ++ } ++ files ++ } ++ ++ fun dirtyLookupSymbolsFromRemovedKotlinFiles(): List { ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ return if (removedKotlinFiles.isNotEmpty()) ++ targets.flatMap { getIncrementalCache(it).classesBySources(removedKotlinFiles).map { LookupSymbol(it.fqNameForClassNameWithoutDollars.shortName().toString(), it.packageFqName.toString()) } } ++ else listOf() ++ } ++ ++ fun dirtyLookupSymbolsFromModifiedJavaFiles(): List { ++ val modifiedJavaFiles = modified.filter { it.isJavaFile() } ++ return (if (modifiedJavaFiles.any()) { ++ val rootDisposable = Disposer.newDisposable() ++ val configuration = CompilerConfiguration() ++ val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) ++ val project = environment.project ++ val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl ++ modifiedJavaFiles.flatMap { ++ val javaFile = psiFileFactory.createFileFromText(it.nameWithoutExtension, Language.findLanguageByID(""JAVA"")!!, it.readText()) ++ if (javaFile is PsiJavaFile) ++ javaFile.classes.flatMap { it.findLookupSymbols() } ++ else listOf() ++ } ++ } else listOf()) ++ } ++ ++ fun dirtyKotlinSourcesFromGradle(): List { ++ // TODO: handle classpath changes similarly - compare with cashed version (likely a big change, may be costly, some heuristics could be considered) ++ val modifiedKotlinFiles = modified.filter { it.isKotlinFile() } ++ val lookupSymbols = ++ dirtyLookupSymbolsFromModifiedJavaFiles() + ++ dirtyLookupSymbolsFromRemovedKotlinFiles() ++ // TODO: add dirty lookups from modified kotlin files to reduce number of steps needed ++ ++ if (lookupSymbols.any()) { ++ val kotlinModifiedFilesSet = modifiedKotlinFiles.toHashSet() ++ return modifiedKotlinFiles + ++ lookupSymbols.files( ++ filesFilter = { it !in kotlinModifiedFilesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ } ++ return modifiedKotlinFiles ++ } ++ ++ fun isClassPathChanged(): Boolean { ++ // TODO: that doesn't look to wise - join it first and then split here, consider storing it somewhere in between ++ val classpath = args.classpath.split(File.pathSeparator).map { File(it) }.toHashSet() ++ val changedClasspath = modified.filter { classpath.contains(it) } ++ return changedClasspath.any() ++ } ++ ++ fun allCachesVersions() = allCachesVersions(cachesBaseDir, listOf(cachesBaseDir)) ++ ++ fun calculateSourcesToCompile(): Pair, Boolean> { ++ ++ if (!experimentalIncremental || ++ !isIncrementalRequested || ++ // TODO: more precise will be not to rebuild unconditionally on classpath changes, but retrieve lookup info and try to find out which sources are affected by cp changes ++ isClassPathChanged() || ++ // so far considering it not incremental TODO: store java files in the cache and extract removed symbols from it here ++ removed.any { it.isJavaFile() } ++ ) { ++ logger.kotlinInfo(if (!isIncrementalRequested) ""clean caches on rebuild"" else ""classpath changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ val actions = if (isIncrementalRequested) allCachesVersions().map { it.checkVersion() } ++ else listOf(CacheVersion.Action.REBUILD_ALL_KOTLIN) ++ // TODO: find out whether these flags should be emulated too ++// val hasKotlin = HasKotlinMarker(dataManager) ++// val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager) ++ ++ for (status in actions.distinct().sorted()) { ++ when (status) { ++ CacheVersion.Action.REBUILD_ALL_KOTLIN -> { ++ logger.kotlinInfo(""Kotlin global lookup map format changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ CacheVersion.Action.REBUILD_CHUNK -> { ++ logger.kotlinInfo(""Clearing caches for "" + targets.joinToString { it.name }) ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_NORMAL_CACHES -> { ++ logger.kotlinInfo(""Clearing caches for all targets"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_EXPERIMENTAL_CACHES -> { ++ logger.kotlinInfo(""Clearing experimental caches for all targets"") ++ targets.forEach { getIncrementalCache(it).cleanExperimental() } ++ } ++ CacheVersion.Action.CLEAN_DATA_CONTAINER -> { ++ logger.kotlinInfo(""Clearing lookup cache"") ++ lookupStorage.clean() ++ dataContainerCacheVersion(cachesBaseDir).clean() ++ } ++ else -> { ++ assert(status == CacheVersion.Action.DO_NOTHING) { ""Unknown version status $status"" } ++ } ++ } ++ } ++ val dirtyFiles = dirtyKotlinSourcesFromGradle().distinct() ++ // first dirty files should be found and only then caches cleared ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ targets.forEach { getIncrementalCache(it).let { ++ it.markOutputClassesDirty(removedKotlinFiles) ++ it.removeClassfilesBySources(removedKotlinFiles) ++ }} ++ return Pair(dirtyFiles, true) ++ } ++ ++ fun cleanupOnError() { ++ val outputDirFile = File(args.destination!!) ++ ++ assert(outputDirFile.exists()) ++ val generatedRelPaths = allGeneratedFiles.map { it.outputFile.toRelativeString(outputDirFile) } ++ logger.kotlinInfo(""deleting output on error: ${generatedRelPaths.joinToString()}"") ++ ++ allGeneratedFiles.forEach { it.outputFile.delete() } ++ generatedRelPaths.forEach { File(destinationDir, it).delete() } ++ } ++ ++ fun processCompilerExitCode(exitCode: ExitCode) { ++ if (exitCode != ExitCode.OK) { ++ cleanupOnError() ++ } ++ when (exitCode) { ++ ExitCode.COMPILATION_ERROR -> throw GradleException(""Compilation error. See log for more details"") ++ ExitCode.INTERNAL_ERROR -> throw GradleException(""Internal compiler error. See log for more details"") ++ ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException(""Script execution error. See log for more details"") ++ ExitCode.OK -> logger.kotlinInfo(""Compilation succeeded"") ++ } ++ } ++ ++ fun outputRelativePath(f: File) = f.toRelativeString(outputDir) ++ ++ ++ if (!experimentalIncremental) { ++ anyClassesCompiled = true ++ processCompilerExitCode(compileNotIncremental(sources, outputDir, args)) ++ return ++ } ++ logger.warn(""Using experimental kotlin incremental compilation"") ++ ++ anyClassesCompiled = false ++ ++ // TODO: decide what to do if no files are considered dirty - rebuild or skip the module ++ var (sourcesToCompile, isIncrementalDecided) = calculateSourcesToCompile() ++ ++ if (isIncrementalDecided) { ++ // TODO: process as list here, merge into string later ++ args.classpath = args.classpath + File.pathSeparator + outputDir.absolutePath ++ } ++ ++ while (sourcesToCompile.any()) { ++ logger.kotlinInfo(""compile iteration: ${sourcesToCompile.joinToString{ projectRelativePath(it) }}"") ++ ++ val (exitCode, generatedFiles) = compileChanged( ++ targets = targets, ++ sourcesToCompile = sourcesToCompile, ++ outputDir = outputDir, ++ args = args, ++ getIncrementalCache = ::getIncrementalCache, ++ lookupTracker = lookupTracker) ++ ++ allGeneratedFiles.addAll(generatedFiles) ++ // save versions? ++ ++ val changes = updateIncrementalCaches( ++ targets = targets, ++ generatedFiles = generatedFiles, ++ compiledWithErrors = exitCode != ExitCode.OK, ++ getIncrementalCache = { caches[it]!! }) ++ ++// lookupTracker.lookups.entrySet().forEach { ++// logger.kotlinDebug(""lookups to ${it.key.name}:${it.key.scope} from ${it.value.joinToString { projectRelativePath(it) }}"") ++// } ++ ++ lookupStorage.update(lookupTracker, sourcesToCompile, currentRemoved) ++ ++ allCachesVersions().forEach { it.saveIfNeeded() }","I believe saving versions should be after the loop. +",2016-02-02 18:14:51 +507,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl { ++ val cacheDir = File(cachesBaseDir, ""increCache.${target.name}"") ++ cacheDir.mkdirs() ++ return GradleIncrementalCacheImpl(targetDataRoot = cacheDir, targetOutputDir = outputDir, target = target) ++ } ++ ++ fun getIncrementalCache(it: TargetId) = caches.getOrPut(it, { getOrCreateIncrementalCache(it) }) ++ ++ fun PsiClass.findLookupSymbols(): Iterable { ++ val fqn = qualifiedName.orEmpty() ++ return listOf(LookupSymbol(name.orEmpty(), if (fqn == name) """" else fqn.removeSuffix(""."" + name!!))) + ++ methods.map { LookupSymbol(it.name, fqn) } + ++ fields.map { LookupSymbol(it.name.orEmpty(), fqn) } + ++ innerClasses.flatMap { it.findLookupSymbols() } ++ } ++ ++ fun Iterable.files(filesFilter: (File) -> Boolean = { true }, logAction: (LookupSymbol, Iterable) -> Unit = { l,fs -> }): Iterable = ++ flatMap { lookup -> ++ val files = lookupStorage.get(lookup).map(::File).filter(filesFilter) ++ if (files.any()) { ++ logAction(lookup, files) ++ } ++ files ++ } ++ ++ fun dirtyLookupSymbolsFromRemovedKotlinFiles(): List { ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ return if (removedKotlinFiles.isNotEmpty()) ++ targets.flatMap { getIncrementalCache(it).classesBySources(removedKotlinFiles).map { LookupSymbol(it.fqNameForClassNameWithoutDollars.shortName().toString(), it.packageFqName.toString()) } } ++ else listOf() ++ } ++ ++ fun dirtyLookupSymbolsFromModifiedJavaFiles(): List { ++ val modifiedJavaFiles = modified.filter { it.isJavaFile() } ++ return (if (modifiedJavaFiles.any()) { ++ val rootDisposable = Disposer.newDisposable() ++ val configuration = CompilerConfiguration() ++ val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) ++ val project = environment.project ++ val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl ++ modifiedJavaFiles.flatMap { ++ val javaFile = psiFileFactory.createFileFromText(it.nameWithoutExtension, Language.findLanguageByID(""JAVA"")!!, it.readText()) ++ if (javaFile is PsiJavaFile) ++ javaFile.classes.flatMap { it.findLookupSymbols() } ++ else listOf() ++ } ++ } else listOf()) ++ } ++ ++ fun dirtyKotlinSourcesFromGradle(): List { ++ // TODO: handle classpath changes similarly - compare with cashed version (likely a big change, may be costly, some heuristics could be considered) ++ val modifiedKotlinFiles = modified.filter { it.isKotlinFile() } ++ val lookupSymbols = ++ dirtyLookupSymbolsFromModifiedJavaFiles() + ++ dirtyLookupSymbolsFromRemovedKotlinFiles() ++ // TODO: add dirty lookups from modified kotlin files to reduce number of steps needed ++ ++ if (lookupSymbols.any()) { ++ val kotlinModifiedFilesSet = modifiedKotlinFiles.toHashSet() ++ return modifiedKotlinFiles + ++ lookupSymbols.files( ++ filesFilter = { it !in kotlinModifiedFilesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ } ++ return modifiedKotlinFiles ++ } ++ ++ fun isClassPathChanged(): Boolean { ++ // TODO: that doesn't look to wise - join it first and then split here, consider storing it somewhere in between ++ val classpath = args.classpath.split(File.pathSeparator).map { File(it) }.toHashSet() ++ val changedClasspath = modified.filter { classpath.contains(it) } ++ return changedClasspath.any() ++ } ++ ++ fun allCachesVersions() = allCachesVersions(cachesBaseDir, listOf(cachesBaseDir)) ++ ++ fun calculateSourcesToCompile(): Pair, Boolean> { ++ ++ if (!experimentalIncremental || ++ !isIncrementalRequested || ++ // TODO: more precise will be not to rebuild unconditionally on classpath changes, but retrieve lookup info and try to find out which sources are affected by cp changes ++ isClassPathChanged() || ++ // so far considering it not incremental TODO: store java files in the cache and extract removed symbols from it here ++ removed.any { it.isJavaFile() } ++ ) { ++ logger.kotlinInfo(if (!isIncrementalRequested) ""clean caches on rebuild"" else ""classpath changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ val actions = if (isIncrementalRequested) allCachesVersions().map { it.checkVersion() } ++ else listOf(CacheVersion.Action.REBUILD_ALL_KOTLIN) ++ // TODO: find out whether these flags should be emulated too ++// val hasKotlin = HasKotlinMarker(dataManager) ++// val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager) ++ ++ for (status in actions.distinct().sorted()) { ++ when (status) { ++ CacheVersion.Action.REBUILD_ALL_KOTLIN -> { ++ logger.kotlinInfo(""Kotlin global lookup map format changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ CacheVersion.Action.REBUILD_CHUNK -> { ++ logger.kotlinInfo(""Clearing caches for "" + targets.joinToString { it.name }) ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_NORMAL_CACHES -> { ++ logger.kotlinInfo(""Clearing caches for all targets"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_EXPERIMENTAL_CACHES -> { ++ logger.kotlinInfo(""Clearing experimental caches for all targets"") ++ targets.forEach { getIncrementalCache(it).cleanExperimental() } ++ } ++ CacheVersion.Action.CLEAN_DATA_CONTAINER -> { ++ logger.kotlinInfo(""Clearing lookup cache"") ++ lookupStorage.clean() ++ dataContainerCacheVersion(cachesBaseDir).clean() ++ } ++ else -> { ++ assert(status == CacheVersion.Action.DO_NOTHING) { ""Unknown version status $status"" } ++ } ++ } ++ } ++ val dirtyFiles = dirtyKotlinSourcesFromGradle().distinct() ++ // first dirty files should be found and only then caches cleared ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ targets.forEach { getIncrementalCache(it).let { ++ it.markOutputClassesDirty(removedKotlinFiles) ++ it.removeClassfilesBySources(removedKotlinFiles) ++ }} ++ return Pair(dirtyFiles, true) ++ } ++ ++ fun cleanupOnError() { ++ val outputDirFile = File(args.destination!!) ++ ++ assert(outputDirFile.exists()) ++ val generatedRelPaths = allGeneratedFiles.map { it.outputFile.toRelativeString(outputDirFile) } ++ logger.kotlinInfo(""deleting output on error: ${generatedRelPaths.joinToString()}"") ++ ++ allGeneratedFiles.forEach { it.outputFile.delete() } ++ generatedRelPaths.forEach { File(destinationDir, it).delete() } ++ } ++ ++ fun processCompilerExitCode(exitCode: ExitCode) { ++ if (exitCode != ExitCode.OK) { ++ cleanupOnError() ++ } ++ when (exitCode) { ++ ExitCode.COMPILATION_ERROR -> throw GradleException(""Compilation error. See log for more details"") ++ ExitCode.INTERNAL_ERROR -> throw GradleException(""Internal compiler error. See log for more details"") ++ ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException(""Script execution error. See log for more details"") ++ ExitCode.OK -> logger.kotlinInfo(""Compilation succeeded"") ++ } ++ } ++ ++ fun outputRelativePath(f: File) = f.toRelativeString(outputDir) ++ ++ ++ if (!experimentalIncremental) { ++ anyClassesCompiled = true ++ processCompilerExitCode(compileNotIncremental(sources, outputDir, args)) ++ return ++ } ++ logger.warn(""Using experimental kotlin incremental compilation"") ++ ++ anyClassesCompiled = false ++ ++ // TODO: decide what to do if no files are considered dirty - rebuild or skip the module ++ var (sourcesToCompile, isIncrementalDecided) = calculateSourcesToCompile() ++ ++ if (isIncrementalDecided) { ++ // TODO: process as list here, merge into string later ++ args.classpath = args.classpath + File.pathSeparator + outputDir.absolutePath ++ } ++ ++ while (sourcesToCompile.any()) { ++ logger.kotlinInfo(""compile iteration: ${sourcesToCompile.joinToString{ projectRelativePath(it) }}"") ++ ++ val (exitCode, generatedFiles) = compileChanged( ++ targets = targets, ++ sourcesToCompile = sourcesToCompile, ++ outputDir = outputDir, ++ args = args, ++ getIncrementalCache = ::getIncrementalCache, ++ lookupTracker = lookupTracker) ++ ++ allGeneratedFiles.addAll(generatedFiles) ++ // save versions? ++ ++ val changes = updateIncrementalCaches( ++ targets = targets, ++ generatedFiles = generatedFiles, ++ compiledWithErrors = exitCode != ExitCode.OK, ++ getIncrementalCache = { caches[it]!! }) ++ ++// lookupTracker.lookups.entrySet().forEach { ++// logger.kotlinDebug(""lookups to ${it.key.name}:${it.key.scope} from ${it.value.joinToString { projectRelativePath(it) }}"") ++// } ++ ++ lookupStorage.update(lookupTracker, sourcesToCompile, currentRemoved) ++ ++ allCachesVersions().forEach { it.saveIfNeeded() } ++ ++ processCompilerExitCode(exitCode) ++ ++ if (!isIncrementalDecided) break; ++ ++// logger.kotlinDebug(""generated ${generatedFiles.joinToString { outputRelativePath(it.outputFile) }}"") ++// logger.kotlinDebug(""changes: ${changes.changes.joinToString { ""${it.fqName}: ${it.javaClass.simpleName}"" }}"") ++// ++// logger.kotlinLazyDebug({ ++// ""known lookups:\n${lookupStorage.dump(changes.changes.flatMap { ++// change -> ++// if (change is ChangeInfo.MembersChanged) ++// change.names.asSequence().map { LookupSymbol(it, change.fqName.asString()) } ++// else ++// sequenceOf() ++// }.toSet(), project.projectDir)}"" }) ++ ++ compiledSourcesSet.addAll(sourcesToCompile) ++ ++ val dirtyLookups = changes.dirtyLookups(caches.values.asSequence()) ++ ++// logger.kotlinDebug(""dirty lookups: ${dirtyLookups.joinToString { ""${it.name}:${it.scope}"" }}"") ++ ++ val dirty = dirtyLookups.files( ++ filesFilter = { it !in compiledSourcesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ sourcesToCompile = dirty.filter { it in sources }.toList()","Minor: `filter` returns list +",2016-02-02 18:17:41 +508,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl { ++ val cacheDir = File(cachesBaseDir, ""increCache.${target.name}"") ++ cacheDir.mkdirs() ++ return GradleIncrementalCacheImpl(targetDataRoot = cacheDir, targetOutputDir = outputDir, target = target) ++ } ++ ++ fun getIncrementalCache(it: TargetId) = caches.getOrPut(it, { getOrCreateIncrementalCache(it) }) ++ ++ fun PsiClass.findLookupSymbols(): Iterable { ++ val fqn = qualifiedName.orEmpty() ++ return listOf(LookupSymbol(name.orEmpty(), if (fqn == name) """" else fqn.removeSuffix(""."" + name!!))) + ++ methods.map { LookupSymbol(it.name, fqn) } + ++ fields.map { LookupSymbol(it.name.orEmpty(), fqn) } + ++ innerClasses.flatMap { it.findLookupSymbols() } ++ } ++ ++ fun Iterable.files(filesFilter: (File) -> Boolean = { true }, logAction: (LookupSymbol, Iterable) -> Unit = { l,fs -> }): Iterable = ++ flatMap { lookup -> ++ val files = lookupStorage.get(lookup).map(::File).filter(filesFilter) ++ if (files.any()) { ++ logAction(lookup, files) ++ } ++ files ++ } ++ ++ fun dirtyLookupSymbolsFromRemovedKotlinFiles(): List { ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ return if (removedKotlinFiles.isNotEmpty()) ++ targets.flatMap { getIncrementalCache(it).classesBySources(removedKotlinFiles).map { LookupSymbol(it.fqNameForClassNameWithoutDollars.shortName().toString(), it.packageFqName.toString()) } } ++ else listOf() ++ } ++ ++ fun dirtyLookupSymbolsFromModifiedJavaFiles(): List { ++ val modifiedJavaFiles = modified.filter { it.isJavaFile() } ++ return (if (modifiedJavaFiles.any()) { ++ val rootDisposable = Disposer.newDisposable() ++ val configuration = CompilerConfiguration() ++ val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) ++ val project = environment.project ++ val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl ++ modifiedJavaFiles.flatMap { ++ val javaFile = psiFileFactory.createFileFromText(it.nameWithoutExtension, Language.findLanguageByID(""JAVA"")!!, it.readText()) ++ if (javaFile is PsiJavaFile) ++ javaFile.classes.flatMap { it.findLookupSymbols() } ++ else listOf() ++ } ++ } else listOf()) ++ } ++ ++ fun dirtyKotlinSourcesFromGradle(): List { ++ // TODO: handle classpath changes similarly - compare with cashed version (likely a big change, may be costly, some heuristics could be considered) ++ val modifiedKotlinFiles = modified.filter { it.isKotlinFile() } ++ val lookupSymbols = ++ dirtyLookupSymbolsFromModifiedJavaFiles() + ++ dirtyLookupSymbolsFromRemovedKotlinFiles() ++ // TODO: add dirty lookups from modified kotlin files to reduce number of steps needed ++ ++ if (lookupSymbols.any()) { ++ val kotlinModifiedFilesSet = modifiedKotlinFiles.toHashSet() ++ return modifiedKotlinFiles + ++ lookupSymbols.files( ++ filesFilter = { it !in kotlinModifiedFilesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ } ++ return modifiedKotlinFiles ++ } ++ ++ fun isClassPathChanged(): Boolean { ++ // TODO: that doesn't look to wise - join it first and then split here, consider storing it somewhere in between ++ val classpath = args.classpath.split(File.pathSeparator).map { File(it) }.toHashSet() ++ val changedClasspath = modified.filter { classpath.contains(it) } ++ return changedClasspath.any() ++ } ++ ++ fun allCachesVersions() = allCachesVersions(cachesBaseDir, listOf(cachesBaseDir)) ++ ++ fun calculateSourcesToCompile(): Pair, Boolean> { ++ ++ if (!experimentalIncremental || ++ !isIncrementalRequested || ++ // TODO: more precise will be not to rebuild unconditionally on classpath changes, but retrieve lookup info and try to find out which sources are affected by cp changes ++ isClassPathChanged() || ++ // so far considering it not incremental TODO: store java files in the cache and extract removed symbols from it here ++ removed.any { it.isJavaFile() } ++ ) { ++ logger.kotlinInfo(if (!isIncrementalRequested) ""clean caches on rebuild"" else ""classpath changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ val actions = if (isIncrementalRequested) allCachesVersions().map { it.checkVersion() } ++ else listOf(CacheVersion.Action.REBUILD_ALL_KOTLIN) ++ // TODO: find out whether these flags should be emulated too ++// val hasKotlin = HasKotlinMarker(dataManager) ++// val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager) ++ ++ for (status in actions.distinct().sorted()) { ++ when (status) { ++ CacheVersion.Action.REBUILD_ALL_KOTLIN -> { ++ logger.kotlinInfo(""Kotlin global lookup map format changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ CacheVersion.Action.REBUILD_CHUNK -> { ++ logger.kotlinInfo(""Clearing caches for "" + targets.joinToString { it.name }) ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_NORMAL_CACHES -> { ++ logger.kotlinInfo(""Clearing caches for all targets"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_EXPERIMENTAL_CACHES -> { ++ logger.kotlinInfo(""Clearing experimental caches for all targets"") ++ targets.forEach { getIncrementalCache(it).cleanExperimental() } ++ } ++ CacheVersion.Action.CLEAN_DATA_CONTAINER -> { ++ logger.kotlinInfo(""Clearing lookup cache"") ++ lookupStorage.clean() ++ dataContainerCacheVersion(cachesBaseDir).clean() ++ } ++ else -> { ++ assert(status == CacheVersion.Action.DO_NOTHING) { ""Unknown version status $status"" } ++ } ++ } ++ } ++ val dirtyFiles = dirtyKotlinSourcesFromGradle().distinct() ++ // first dirty files should be found and only then caches cleared ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ targets.forEach { getIncrementalCache(it).let { ++ it.markOutputClassesDirty(removedKotlinFiles) ++ it.removeClassfilesBySources(removedKotlinFiles) ++ }} ++ return Pair(dirtyFiles, true) ++ } ++ ++ fun cleanupOnError() { ++ val outputDirFile = File(args.destination!!) ++ ++ assert(outputDirFile.exists()) ++ val generatedRelPaths = allGeneratedFiles.map { it.outputFile.toRelativeString(outputDirFile) } ++ logger.kotlinInfo(""deleting output on error: ${generatedRelPaths.joinToString()}"") ++ ++ allGeneratedFiles.forEach { it.outputFile.delete() } ++ generatedRelPaths.forEach { File(destinationDir, it).delete() } ++ } ++ ++ fun processCompilerExitCode(exitCode: ExitCode) { ++ if (exitCode != ExitCode.OK) { ++ cleanupOnError() ++ } ++ when (exitCode) { ++ ExitCode.COMPILATION_ERROR -> throw GradleException(""Compilation error. See log for more details"") ++ ExitCode.INTERNAL_ERROR -> throw GradleException(""Internal compiler error. See log for more details"") ++ ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException(""Script execution error. See log for more details"") ++ ExitCode.OK -> logger.kotlinInfo(""Compilation succeeded"") ++ } ++ } ++ ++ fun outputRelativePath(f: File) = f.toRelativeString(outputDir) ++ ++ ++ if (!experimentalIncremental) { ++ anyClassesCompiled = true ++ processCompilerExitCode(compileNotIncremental(sources, outputDir, args)) ++ return ++ } ++ logger.warn(""Using experimental kotlin incremental compilation"") ++ ++ anyClassesCompiled = false ++ ++ // TODO: decide what to do if no files are considered dirty - rebuild or skip the module ++ var (sourcesToCompile, isIncrementalDecided) = calculateSourcesToCompile() ++ ++ if (isIncrementalDecided) { ++ // TODO: process as list here, merge into string later ++ args.classpath = args.classpath + File.pathSeparator + outputDir.absolutePath ++ } ++ ++ while (sourcesToCompile.any()) { ++ logger.kotlinInfo(""compile iteration: ${sourcesToCompile.joinToString{ projectRelativePath(it) }}"") ++ ++ val (exitCode, generatedFiles) = compileChanged( ++ targets = targets, ++ sourcesToCompile = sourcesToCompile, ++ outputDir = outputDir, ++ args = args, ++ getIncrementalCache = ::getIncrementalCache, ++ lookupTracker = lookupTracker) ++ ++ allGeneratedFiles.addAll(generatedFiles) ++ // save versions? ++ ++ val changes = updateIncrementalCaches( ++ targets = targets, ++ generatedFiles = generatedFiles, ++ compiledWithErrors = exitCode != ExitCode.OK, ++ getIncrementalCache = { caches[it]!! }) ++ ++// lookupTracker.lookups.entrySet().forEach { ++// logger.kotlinDebug(""lookups to ${it.key.name}:${it.key.scope} from ${it.value.joinToString { projectRelativePath(it) }}"") ++// } ++ ++ lookupStorage.update(lookupTracker, sourcesToCompile, currentRemoved) ++ ++ allCachesVersions().forEach { it.saveIfNeeded() } ++ ++ processCompilerExitCode(exitCode) ++ ++ if (!isIncrementalDecided) break; ++ ++// logger.kotlinDebug(""generated ${generatedFiles.joinToString { outputRelativePath(it.outputFile) }}"") ++// logger.kotlinDebug(""changes: ${changes.changes.joinToString { ""${it.fqName}: ${it.javaClass.simpleName}"" }}"") ++// ++// logger.kotlinLazyDebug({ ++// ""known lookups:\n${lookupStorage.dump(changes.changes.flatMap { ++// change -> ++// if (change is ChangeInfo.MembersChanged) ++// change.names.asSequence().map { LookupSymbol(it, change.fqName.asString()) } ++// else ++// sequenceOf() ++// }.toSet(), project.projectDir)}"" }) ++ ++ compiledSourcesSet.addAll(sourcesToCompile) ++ ++ val dirtyLookups = changes.dirtyLookups(caches.values.asSequence()) ++ ++// logger.kotlinDebug(""dirty lookups: ${dirtyLookups.joinToString { ""${it.name}:${it.scope}"" }}"") ++ ++ val dirty = dirtyLookups.files( ++ filesFilter = { it !in compiledSourcesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ sourcesToCompile = dirty.filter { it in sources }.toList() ++ if (currentRemoved.any()) { ++ currentRemoved = listOf() ++ } ++// logger.kotlinDebug(""dirty: ${dirty.joinToString { projectRelativePath(it) }}"") ++// logger.kotlinDebug(""to compile: ${sourcesToCompile.joinToString { projectRelativePath(it) }}"") ++ } ++ lookupStorage.flush(false) ++ lookupStorage.close() ++ caches.values.forEach { it.flush(false); it.close() } ++ if (allGeneratedFiles.isNotEmpty()) { ++ anyClassesCompiled = true ++ } ++ } ++ ++ private data class CompileChangedResults(val exitCode: ExitCode, val generatedFiles: List>) ++ ++ private fun compileChanged(targets: List, ++ sourcesToCompile: List, ++ outputDir: File, ++ args: K2JVMCompilerArguments, ++ getIncrementalCache: (TargetId) -> GradleIncrementalCacheImpl, ++ lookupTracker: LookupTracker) ++ : CompileChangedResults","Minor: formatting +",2016-02-02 18:20:30 +509,"@@ -163,16 +217,341 @@ public open class KotlinCompile() : AbstractKotlinCompile, isIncrementalRequested: Boolean, modified: List, removed: List, cachesBaseDir: File) { ++ ++ if (experimentalIncremental) { ++ // TODO: consider other ways to pass incremental flag to compiler/builder ++ System.setProperty(""kotlin.incremental.compilation"", ""true"") ++ // TODO: experimental should be removed as soon as it becomes standard ++ System.setProperty(""kotlin.incremental.compilation.experimental"", ""true"") ++ } ++ ++ val targetType = ""java-production"" ++ val moduleName = args.moduleName ++ val targets = listOf(TargetId(moduleName, targetType)) ++ val outputDir = File(args.destination) ++ val caches = hashMapOf() ++ val lookupStorage = LookupStorage(File(cachesBaseDir, ""lookups"")) ++ val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) ++ var currentRemoved = removed ++ val allGeneratedFiles = hashSetOf>() ++ val compiledSourcesSet = hashSetOf() ++ ++ fun getOrCreateIncrementalCache(target: TargetId): GradleIncrementalCacheImpl { ++ val cacheDir = File(cachesBaseDir, ""increCache.${target.name}"") ++ cacheDir.mkdirs() ++ return GradleIncrementalCacheImpl(targetDataRoot = cacheDir, targetOutputDir = outputDir, target = target) ++ } ++ ++ fun getIncrementalCache(it: TargetId) = caches.getOrPut(it, { getOrCreateIncrementalCache(it) }) ++ ++ fun PsiClass.findLookupSymbols(): Iterable { ++ val fqn = qualifiedName.orEmpty() ++ return listOf(LookupSymbol(name.orEmpty(), if (fqn == name) """" else fqn.removeSuffix(""."" + name!!))) + ++ methods.map { LookupSymbol(it.name, fqn) } + ++ fields.map { LookupSymbol(it.name.orEmpty(), fqn) } + ++ innerClasses.flatMap { it.findLookupSymbols() } ++ } ++ ++ fun Iterable.files(filesFilter: (File) -> Boolean = { true }, logAction: (LookupSymbol, Iterable) -> Unit = { l,fs -> }): Iterable = ++ flatMap { lookup -> ++ val files = lookupStorage.get(lookup).map(::File).filter(filesFilter) ++ if (files.any()) { ++ logAction(lookup, files) ++ } ++ files ++ } ++ ++ fun dirtyLookupSymbolsFromRemovedKotlinFiles(): List { ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ return if (removedKotlinFiles.isNotEmpty()) ++ targets.flatMap { getIncrementalCache(it).classesBySources(removedKotlinFiles).map { LookupSymbol(it.fqNameForClassNameWithoutDollars.shortName().toString(), it.packageFqName.toString()) } } ++ else listOf() ++ } ++ ++ fun dirtyLookupSymbolsFromModifiedJavaFiles(): List { ++ val modifiedJavaFiles = modified.filter { it.isJavaFile() } ++ return (if (modifiedJavaFiles.any()) { ++ val rootDisposable = Disposer.newDisposable() ++ val configuration = CompilerConfiguration() ++ val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) ++ val project = environment.project ++ val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl ++ modifiedJavaFiles.flatMap { ++ val javaFile = psiFileFactory.createFileFromText(it.nameWithoutExtension, Language.findLanguageByID(""JAVA"")!!, it.readText()) ++ if (javaFile is PsiJavaFile) ++ javaFile.classes.flatMap { it.findLookupSymbols() } ++ else listOf() ++ } ++ } else listOf()) ++ } ++ ++ fun dirtyKotlinSourcesFromGradle(): List { ++ // TODO: handle classpath changes similarly - compare with cashed version (likely a big change, may be costly, some heuristics could be considered) ++ val modifiedKotlinFiles = modified.filter { it.isKotlinFile() } ++ val lookupSymbols = ++ dirtyLookupSymbolsFromModifiedJavaFiles() + ++ dirtyLookupSymbolsFromRemovedKotlinFiles() ++ // TODO: add dirty lookups from modified kotlin files to reduce number of steps needed ++ ++ if (lookupSymbols.any()) { ++ val kotlinModifiedFilesSet = modifiedKotlinFiles.toHashSet() ++ return modifiedKotlinFiles + ++ lookupSymbols.files( ++ filesFilter = { it !in kotlinModifiedFilesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ } ++ return modifiedKotlinFiles ++ } ++ ++ fun isClassPathChanged(): Boolean { ++ // TODO: that doesn't look to wise - join it first and then split here, consider storing it somewhere in between ++ val classpath = args.classpath.split(File.pathSeparator).map { File(it) }.toHashSet() ++ val changedClasspath = modified.filter { classpath.contains(it) } ++ return changedClasspath.any() ++ } ++ ++ fun allCachesVersions() = allCachesVersions(cachesBaseDir, listOf(cachesBaseDir)) ++ ++ fun calculateSourcesToCompile(): Pair, Boolean> { ++ ++ if (!experimentalIncremental || ++ !isIncrementalRequested || ++ // TODO: more precise will be not to rebuild unconditionally on classpath changes, but retrieve lookup info and try to find out which sources are affected by cp changes ++ isClassPathChanged() || ++ // so far considering it not incremental TODO: store java files in the cache and extract removed symbols from it here ++ removed.any { it.isJavaFile() } ++ ) { ++ logger.kotlinInfo(if (!isIncrementalRequested) ""clean caches on rebuild"" else ""classpath changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ val actions = if (isIncrementalRequested) allCachesVersions().map { it.checkVersion() } ++ else listOf(CacheVersion.Action.REBUILD_ALL_KOTLIN) ++ // TODO: find out whether these flags should be emulated too ++// val hasKotlin = HasKotlinMarker(dataManager) ++// val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager) ++ ++ for (status in actions.distinct().sorted()) { ++ when (status) { ++ CacheVersion.Action.REBUILD_ALL_KOTLIN -> { ++ logger.kotlinInfo(""Kotlin global lookup map format changed, rebuilding all kotlin files"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ lookupStorage.clean() ++ return Pair(sources, false) ++ } ++ CacheVersion.Action.REBUILD_CHUNK -> { ++ logger.kotlinInfo(""Clearing caches for "" + targets.joinToString { it.name }) ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_NORMAL_CACHES -> { ++ logger.kotlinInfo(""Clearing caches for all targets"") ++ targets.forEach { getIncrementalCache(it).clean() } ++ } ++ CacheVersion.Action.CLEAN_EXPERIMENTAL_CACHES -> { ++ logger.kotlinInfo(""Clearing experimental caches for all targets"") ++ targets.forEach { getIncrementalCache(it).cleanExperimental() } ++ } ++ CacheVersion.Action.CLEAN_DATA_CONTAINER -> { ++ logger.kotlinInfo(""Clearing lookup cache"") ++ lookupStorage.clean() ++ dataContainerCacheVersion(cachesBaseDir).clean() ++ } ++ else -> { ++ assert(status == CacheVersion.Action.DO_NOTHING) { ""Unknown version status $status"" } ++ } ++ } ++ } ++ val dirtyFiles = dirtyKotlinSourcesFromGradle().distinct() ++ // first dirty files should be found and only then caches cleared ++ val removedKotlinFiles = removed.filter { it.isKotlinFile() } ++ targets.forEach { getIncrementalCache(it).let { ++ it.markOutputClassesDirty(removedKotlinFiles) ++ it.removeClassfilesBySources(removedKotlinFiles) ++ }} ++ return Pair(dirtyFiles, true) ++ } ++ ++ fun cleanupOnError() { ++ val outputDirFile = File(args.destination!!) ++ ++ assert(outputDirFile.exists()) ++ val generatedRelPaths = allGeneratedFiles.map { it.outputFile.toRelativeString(outputDirFile) } ++ logger.kotlinInfo(""deleting output on error: ${generatedRelPaths.joinToString()}"") ++ ++ allGeneratedFiles.forEach { it.outputFile.delete() } ++ generatedRelPaths.forEach { File(destinationDir, it).delete() } ++ } ++ ++ fun processCompilerExitCode(exitCode: ExitCode) { ++ if (exitCode != ExitCode.OK) { ++ cleanupOnError() ++ } ++ when (exitCode) { ++ ExitCode.COMPILATION_ERROR -> throw GradleException(""Compilation error. See log for more details"") ++ ExitCode.INTERNAL_ERROR -> throw GradleException(""Internal compiler error. See log for more details"") ++ ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException(""Script execution error. See log for more details"") ++ ExitCode.OK -> logger.kotlinInfo(""Compilation succeeded"") ++ } ++ } ++ ++ fun outputRelativePath(f: File) = f.toRelativeString(outputDir) ++ ++ ++ if (!experimentalIncremental) { ++ anyClassesCompiled = true ++ processCompilerExitCode(compileNotIncremental(sources, outputDir, args)) ++ return ++ } ++ logger.warn(""Using experimental kotlin incremental compilation"") ++ ++ anyClassesCompiled = false ++ ++ // TODO: decide what to do if no files are considered dirty - rebuild or skip the module ++ var (sourcesToCompile, isIncrementalDecided) = calculateSourcesToCompile() ++ ++ if (isIncrementalDecided) { ++ // TODO: process as list here, merge into string later ++ args.classpath = args.classpath + File.pathSeparator + outputDir.absolutePath ++ } ++ ++ while (sourcesToCompile.any()) { ++ logger.kotlinInfo(""compile iteration: ${sourcesToCompile.joinToString{ projectRelativePath(it) }}"") ++ ++ val (exitCode, generatedFiles) = compileChanged( ++ targets = targets, ++ sourcesToCompile = sourcesToCompile, ++ outputDir = outputDir, ++ args = args, ++ getIncrementalCache = ::getIncrementalCache, ++ lookupTracker = lookupTracker) ++ ++ allGeneratedFiles.addAll(generatedFiles) ++ // save versions? ++ ++ val changes = updateIncrementalCaches( ++ targets = targets, ++ generatedFiles = generatedFiles, ++ compiledWithErrors = exitCode != ExitCode.OK, ++ getIncrementalCache = { caches[it]!! }) ++ ++// lookupTracker.lookups.entrySet().forEach { ++// logger.kotlinDebug(""lookups to ${it.key.name}:${it.key.scope} from ${it.value.joinToString { projectRelativePath(it) }}"") ++// } ++ ++ lookupStorage.update(lookupTracker, sourcesToCompile, currentRemoved) ++ ++ allCachesVersions().forEach { it.saveIfNeeded() } ++ ++ processCompilerExitCode(exitCode) ++ ++ if (!isIncrementalDecided) break; ++ ++// logger.kotlinDebug(""generated ${generatedFiles.joinToString { outputRelativePath(it.outputFile) }}"") ++// logger.kotlinDebug(""changes: ${changes.changes.joinToString { ""${it.fqName}: ${it.javaClass.simpleName}"" }}"") ++// ++// logger.kotlinLazyDebug({ ++// ""known lookups:\n${lookupStorage.dump(changes.changes.flatMap { ++// change -> ++// if (change is ChangeInfo.MembersChanged) ++// change.names.asSequence().map { LookupSymbol(it, change.fqName.asString()) } ++// else ++// sequenceOf() ++// }.toSet(), project.projectDir)}"" }) ++ ++ compiledSourcesSet.addAll(sourcesToCompile) ++ ++ val dirtyLookups = changes.dirtyLookups(caches.values.asSequence()) ++ ++// logger.kotlinDebug(""dirty lookups: ${dirtyLookups.joinToString { ""${it.name}:${it.scope}"" }}"") ++ ++ val dirty = dirtyLookups.files( ++ filesFilter = { it !in compiledSourcesSet }, ++ logAction = { lookup, files -> ++ logger.kotlinInfo(""changes in ${lookup.name} (${lookup.scope}) causes recompilation of ${files.joinToString { projectRelativePath(it) }}"") ++ }) ++ sourcesToCompile = dirty.filter { it in sources }.toList() ++ if (currentRemoved.any()) { ++ currentRemoved = listOf() ++ } ++// logger.kotlinDebug(""dirty: ${dirty.joinToString { projectRelativePath(it) }}"") ++// logger.kotlinDebug(""to compile: ${sourcesToCompile.joinToString { projectRelativePath(it) }}"") ++ } ++ lookupStorage.flush(false) ++ lookupStorage.close() ++ caches.values.forEach { it.flush(false); it.close() } ++ if (allGeneratedFiles.isNotEmpty()) { ++ anyClassesCompiled = true ++ } ++ } ++ ++ private data class CompileChangedResults(val exitCode: ExitCode, val generatedFiles: List>) ++ ++ private fun compileChanged(targets: List, ++ sourcesToCompile: List, ++ outputDir: File, ++ args: K2JVMCompilerArguments, ++ getIncrementalCache: (TargetId) -> GradleIncrementalCacheImpl, ++ lookupTracker: LookupTracker) ++ : CompileChangedResults ++ { ++ // show kotlin compiler where to look for java source files ++ args.freeArgs = (sourcesToCompile.map { it.absolutePath } + getJavaSourceRoots().map { it.absolutePath }).distinct() ++ args.destination = outputDir.absolutePath ++ ++ logger.kotlinDebug(""compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}"") ++ ++ val outputItemCollector = OutputItemsCollectorImpl() ++ ++ val messageCollector = GradleMessageCollector(logger, outputItemCollector) ++ ++ val incrementalCaches = makeIncrementalCachesMap(targets, { listOf() }, getIncrementalCache, { this }) ++ ++ val compilationCanceledStatus = object : CompilationCanceledStatus { ++ override fun checkCanceled() {} ++ } ++ ++ logger.kotlinDebug(""compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}"") ++ ++ val exitCode = compiler.exec(messageCollector, makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus), args) ++ ++ return CompileChangedResults( ++ exitCode, ++ outputItemCollector.generatedFiles( ++ targets = targets, ++ representativeTarget = targets.first(), ++ getSources = { sourcesToCompile }, ++ getOutputDir = { outputDir })) ++ } ++ ++ private fun compileNotIncremental(sourcesToCompile: List, ++ outputDir: File, ++ args: K2JVMCompilerArguments) ++ : ExitCode","Minor: formatting +",2016-02-02 18:20:35 +905,"@@ -168,6 +168,20 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() { + """""".trim().trimMargin(), true) + } + ++ fun testRemoveConstructorParameters() { ++ myFixture.configureByText(""foo.kt"", """""" ++ |class Foo(i: Int) { ++ |} ++ """""".trim().trimMargin()) ++ ++ myFixture.launchAction(codeModifications.createAddCallableMemberActions(MethodInsertionInfo.constructorInfo( ++ atCaret(myFixture), makeParams())).findWithText(""Remove 1st parameter from method 'Foo'""))","It's better to change the intention text so that it says ""constructor"" and not ""method"".",2017-07-17 11:29:15 +472,"@@ -17,12 +17,22 @@ + package org.jetbrains.kotlin.idea.compiler.configuration + + import com.intellij.compiler.server.BuildProcessParametersProvider ++import org.jetbrains.kotlin.idea.PluginStartupComponent + +-public class KotlinBuildProcessParametersProvider(private val compilerWorkspaceSettings: KotlinCompilerWorkspaceSettings): BuildProcessParametersProvider() { ++public class KotlinBuildProcessParametersProvider(private val compilerWorkspaceSettings: KotlinCompilerWorkspaceSettings, ++ private val kotlinPluginStartupComponent: PluginStartupComponent ++): BuildProcessParametersProvider() { + override fun getVMArguments(): MutableList { +- return if (compilerWorkspaceSettings.incrementalCompilationEnabled) +- arrayListOf() +- else +- arrayListOf(""-Dkotlin.incremental.compilation=false"") ++ val res = arrayListOf() ++ if (compilerWorkspaceSettings.incrementalCompilationEnabled) {","Is it ok that behavior changed? +",2015-09-10 11:41:42 +490,"@@ -17,3 +17,11 @@ + package org.jetbrains.kotlin.cli.common + + public val KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY = ""kotlin.environment.keepalive"" ++ ++ ++fun String?.toBooleanLenient(): Boolean? = when (this?.toLowerCase()) {","It seems it is possible to simplify conditional expressions by using the following function instead of `toBooleanLenient` + +``` +fun String.systemPropertyAsBooleanOrTrueOtherwise(negate: Boolean): Boolean { + val propValue = System.getProperty(this) ?: return true + + return when (propValue.toLowerCase()) { + in listOf("""", ""yes"", ""true"", ""on"", ""y"") -> !negate + in listOf(""no"", ""false"", ""off"", ""n"") -> negate + else -> true + } +} +``` + +See comments below. +",2015-11-27 18:20:45 +280,"@@ -17,6 +17,7 @@ + package kotlin + + /** +- * Nothing has no instances ++ * Nothing has no instances. You can use Nothing as the return type of a function to indicate ++ * that it never returns (always throws an exception).","There are more use-cases for Nothing, e.g. Iterable is ok to exist, but it will never enter ""for"" loop, etc. Needs link to lang docs. +",2015-02-09 15:38:44 +668,"@@ -171,11 +171,21 @@ private val stdin: BufferedReader by lazy { BufferedReader(InputStreamReader(obj + public override fun read(b: ByteArray, off: Int, len: Int): Int { + return System.`in`.read(b, off, len) + } +-}))} ++})} + + /** + * Reads a line of input from the standard input stream. + * + * @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached. + */ +-public fun readLine(): String? = stdin.readLine() ++public fun readLine(): String? { ++ tailrec fun readChars(oldBuffer: StringBuffer? = null): StringBuffer? {",Why do you choose `StringBuffer` instead of `StringBuilder`?,2016-12-28 17:03:12 +667,"@@ -171,11 +171,21 @@ private val stdin: BufferedReader by lazy { BufferedReader(InputStreamReader(obj + public override fun read(b: ByteArray, off: Int, len: Int): Int { + return System.`in`.read(b, off, len) + } +-}))} ++})} + + /** + * Reads a line of input from the standard input stream. + * + * @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached. + */ +-public fun readLine(): String? = stdin.readLine() ++public fun readLine(): String? { ++ tailrec fun readChars(oldBuffer: StringBuffer? = null): StringBuffer? { ++ val c = mystdin.read()",What is `mystdin` here?,2016-12-28 17:02:31 +669,"@@ -171,11 +171,21 @@ private val stdin: BufferedReader by lazy { BufferedReader(InputStreamReader(obj + public override fun read(b: ByteArray, off: Int, len: Int): Int { + return System.`in`.read(b, off, len) + } +-}))} ++})} + + /** + * Reads a line of input from the standard input stream. + * + * @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached. + */ +-public fun readLine(): String? = stdin.readLine() ++public fun readLine(): String? { ++ tailrec fun readChars(oldBuffer: StringBuffer? = null): StringBuffer? { ++ val c = mystdin.read() ++ if(c < 0) return oldBuffer ++ val buffer = oldBuffer ?: StringBuffer() ++ val ch = c.toChar() ++ if(ch == '\r' || ch == '\n') return buffer","We should support ""\n"" and ""\r\n"" line delimiters, and ""\r"" alone can be treated like a plain character.",2016-12-28 17:04:59 +670,"@@ -171,11 +171,21 @@ private val stdin: BufferedReader by lazy { BufferedReader(InputStreamReader(obj + public override fun read(b: ByteArray, off: Int, len: Int): Int { + return System.`in`.read(b, off, len) + } +-}))} ++})} + + /** + * Reads a line of input from the standard input stream. + * + * @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached. + */ +-public fun readLine(): String? = stdin.readLine() ++public fun readLine(): String? { ++ tailrec fun readChars(oldBuffer: StringBuffer? = null): StringBuffer? { ++ val c = mystdin.read() ++ if(c < 0) return oldBuffer ++ val buffer = oldBuffer ?: StringBuffer() ++ val ch = c.toChar() ++ if(ch == '\r' || ch == '\n') return buffer ++ return readChars(buffer.append(ch)) ++ } ++ return readChars()?.toString() ++}","Overall, `buildString` + imperative loop might be more clear than tail recursion approach.",2016-12-28 17:06:43 +266,"@@ -171,6 +138,36 @@ public open class KotlinCompile() : AbstractKotlinCompile source"" field from version 1.10 (or 1.11) +",2014-12-26 14:23:23 +289,"@@ -1730,14 +1730,14 @@ public fun Stream.lastOrNull(): T? { + } + + /** +- * Returns last element, or null if collection is empty ++ * Returns the last character, or null if the string is empty + */ + public fun String.lastOrNull(): Char? { + return if (isEmpty()) null else this[length() - 1] + } + + /** +- * Returns last element matching the given *predicate*, or null if element was not found ++ * Returns the last element matching the given [predicate], or *null* if no such element was found.","_null_ -> `null` +",2015-02-09 15:48:49 +881,"@@ -175,6 +175,23 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { + // element is not an KtReferenceExpression, but KtClass of enum + return renderEnum(element, originalElement, quickNavigation) + } ++ else if (element is KtEnumEntry && !quickNavigation) { ++ val desc = element.resolveToDescriptorIfAny() ++ val ordinal =",It's better to calculate ordinal with `val ordinal = element.containingClassOrObject?.run { getChildrenOfType().indexOf(element) }`,2017-07-06 12:32:45 +934,"@@ -18,13 +18,15 @@ package org.jetbrains.kotlin.idea.quickfix + + import com.intellij.openapi.editor.Editor + import com.intellij.openapi.project.Project ++import com.intellij.psi.util.PsiTreeUtil + import org.jetbrains.kotlin.diagnostics.Diagnostic + import org.jetbrains.kotlin.psi.KtFile + import org.jetbrains.kotlin.psi.KtIsExpression + import org.jetbrains.kotlin.psi.KtPsiFactory ++import org.jetbrains.kotlin.psi.KtWhenEntry + import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType + +-class RemoveUselessIsCheckFix(element: KtIsExpression) : KotlinQuickFixAction(element) { ++class RemoveUselessIsCheckFixForIf(element: KtIsExpression) : KotlinQuickFixAction(element) {","Not a good name, may be it's better to leave it as before. This action is applicable also for when without subject, or just for code like `val a = b is Any`.",2017-07-26 15:01:15 +935,"@@ -18,18 +18,17 @@ package org.jetbrains.kotlin.idea.intentions + + import com.intellij.openapi.editor.Editor + import org.jetbrains.kotlin.idea.core.replaced +-import org.jetbrains.kotlin.psi.KtCallExpression +-import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +-import org.jetbrains.kotlin.psi.KtPsiFactory +-import org.jetbrains.kotlin.psi.createExpressionByPattern ++import org.jetbrains.kotlin.psi.* + import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType + + abstract class ReplaceMathMethodsWithKotlinNativeMethodsIntention( +- text: String, val replacedMethodName: String, val mathMethodName: String ++ text: String, private val replacedMethodName: String, private val mathMethodName: String + ) : SelfTargetingOffsetIndependentIntention(KtCallExpression::class.java, text) { + + override fun applyTo(element: KtCallExpression, editor: Editor?) { +- val target = element.getStrictParentOfType() ?: element ++ val target = element.getStrictParentOfType()?.takeIf { ++ (it.receiverExpression as? KtNameReferenceExpression)?.getReferencedName() == ""Math"" ++ } ?: element","It's also not the best way, you can meet something like + +``` +Math.max(max(1, 3), max(2, 4)) +``` + +and will have the same problem. Will fix it myself.",2017-07-26 16:51:40 +466,"@@ -18,246 +18,376 @@ package org.jetbrains.kotlin.rmi.kotlinr + + import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache + import org.jetbrains.kotlin.rmi.* +-import java.io.File +-import java.io.OutputStream +-import java.io.PrintStream ++import java.io.* + import java.rmi.ConnectException +-import java.rmi.Remote + import java.rmi.registry.LocateRegistry + import java.util.concurrent.Semaphore + import java.util.concurrent.TimeUnit + import kotlin.concurrent.thread + +-fun Process.isAlive() = ++ ++public object KotlinCompilerClient { ++ ++ val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3 ++ ++ ++ // TODO: remove jvmStatic after all use sites will switch to kotlin ++ jvmStatic ++ public fun connectToCompileService(compilerId: CompilerId, ++ daemonJVMOptions: DaemonJVMOptions, ++ daemonOptions: DaemonOptions, ++ reportingTargets: DaemonReportingTargets, ++ autostart: Boolean = true, ++ checkId: Boolean = true ++ ): CompileService? { ++ ++ var attempts = 0 ++ var fileLock: FileBasedLock? = null + try { +- this.exitValue() +- false ++ while (attempts++ < DAEMON_CONNECT_CYCLE_ATTEMPTS) { ++ val service = tryFindDaemon(File(daemonOptions.runFilesPath), compilerId, reportingTargets) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId)) { ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""connected to the daemon"") ++ return service ++ } ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""compiler identity don't match: "" + compilerId.mappers.flatMap { it.toArgs("""") }.joinToString("" "")) ++ if (!autostart) return null ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""daemon shut down correctly, restarting search"") ++ } ++ else { ++ if (!autostart) return null ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""no suitable daemon found, starting a new one"") ++ } ++ ++ if (fileLock == null || !fileLock.isLocked()) { ++ File(daemonOptions.runFilesPath).mkdirs() ++ fileLock = FileBasedLock(compilerId, daemonOptions) ++ // need to check the daemons again here, because of possible racing conditions ++ // note: the algorithm could be simpler if we'll acquire lock right from the beginning, but it may be costly ++ attempts-- ++ } ++ else { ++ startDaemon(compilerId, daemonJVMOptions, daemonOptions, reportingTargets) ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""daemon started, trying to resolve"") ++ } ++ } + } +- catch (e: IllegalThreadStateException) { +- true ++ catch (e: Exception) { ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, e.toString()) ++ } ++ finally { ++ fileLock?.release() + } ++ return null ++ } + +-public class KotlinCompilerClient { + +- companion object { ++ public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, DaemonReportingTargets(out = System.out), autostart = false, checkId = false) ++ ?.shutdown() ++ } + +- val DAEMON_STARTUP_TIMEOUT_MS = 10000L + +- private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ public fun shutdownCompileService(): Unit { ++ shutdownCompileService(DaemonOptions()) ++ } + +- val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running +- return compilerObj as? CompileService ?: +- throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ ++ public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ try { ++ return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN, outStrm) + } ++ finally { ++ outStrm.disconnect() ++ } ++ } + +- private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { +- try { +- val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) +- ?.lookup(COMPILER_SERVICE_RMI_NAME) +- if (daemon != null) +- return daemon +- errStream.println(""[daemon client] daemon not found"") +- } +- catch (e: ConnectException) { +- errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) +- // ignoring it - processing below +- } +- return null ++ ++ // TODO: remove jvmStatic after all use sites will switch to kotlin ++ jvmStatic ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, compilerOut: OutputStream, daemonOut: OutputStream): Int { ++ ++ val compilerOutStreamServer = RemoteOutputStreamServer(compilerOut) ++ val daemonOutStreamServer = RemoteOutputStreamServer(daemonOut) ++ val cacheServers = hashMapOf() ++ try { ++ caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer(it.getValue()) }) ++ return compiler.remoteIncrementalCompile(args, cacheServers, compilerOutStreamServer, CompileService.OutputFormat.XML, daemonOutStreamServer) ++ } ++ finally { ++ cacheServers.forEach { it.getValue().disconnect() } ++ compilerOutStreamServer.disconnect() ++ daemonOutStreamServer.disconnect() + } ++ } + + +- private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { +- val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { +- val javaw = File(it, ""javaw.exe"") +- if (javaw.exists()) javaw +- else File(it, ""java"") +- } +- // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs +- val args = listOf(javaExecutable.absolutePath, +- ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + +- daemonJVMOptions.mappers.flatMap { it.toArgs(""-"") } + +- COMPILER_DAEMON_CLASS_FQN + +- daemonOptions.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + +- compilerId.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } +- errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) +- val processBuilder = ProcessBuilder(args).redirectErrorStream(true) +- // assuming daemon process is deaf and (mostly) silent, so do not handle streams +- val daemon = processBuilder.start() +- +- var isEchoRead = Semaphore(1) +- isEchoRead.acquire() +- +- val stdoutThread = +- thread { +- daemon.getInputStream() +- .reader() +- .forEachLine { +- if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) { +- isEchoRead.release() +- return@forEachLine +- } +- errStream.println(""[daemon] "" + it) +- } +- } +- try { +- // trying to wait for process +- if (daemonOptions.startEcho.isNotEmpty()) { +- errStream.println(""[daemon client] waiting for daemon to respond"") +- val succeeded = isEchoRead.tryAcquire(DAEMON_STARTUP_TIMEOUT_MS, TimeUnit.MILLISECONDS) +- if (!daemon.isAlive()) +- throw Exception(""Daemon terminated unexpectedly"") +- if (!succeeded) +- throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") +- } +- else +- // without startEcho defined waiting for max timeout +- Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) +- } +- finally { +- // assuming that all important output is already done, the rest should be routed to the log by the daemon itself +- if (stdoutThread.isAlive) +- // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream +- stdoutThread.stop() ++ data class ClientOptions( ++ public var stop: Boolean = false ++ ) : OptionsGroup { ++ override val mappers: List> ++ get() = listOf(BoolPropMapper(this, ::stop)) ++ } ++ ++ ++ jvmStatic public fun main(vararg args: String) { ++ val compilerId = CompilerId() ++ val daemonOptions = DaemonOptions() ++ val daemonLaunchingOptions = DaemonJVMOptions() ++ val clientOptions = ClientOptions() ++ val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) ++ ++ if (!clientOptions.stop) { ++ if (compilerId.compilerClasspath.none()) { ++ // attempt to find compiler to use ++ System.err.println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") ++ System.getProperty(""java.class.path"") ++ ?.split(File.pathSeparator) ++ ?.map { File(it).parentFile } ++ ?.distinct() ++ ?.map { ++ it?.walk() ++ ?.firstOrNull { it.name.equals(COMPILER_JAR_NAME, ignoreCase = true) } ++ } ++ ?.filterNotNull() ++ ?.firstOrNull() ++ ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } + } +- } ++ if (compilerId.compilerClasspath.none()) ++ throw IllegalArgumentException(""Cannot find compiler jar"") ++ else ++ println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) + +- public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { +- val remoteId = compiler.getCompilerId() +- errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) +- errStream.println(""[daemon client] localId = "" + localId.toString()) +- return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && +- (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && +- (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ compilerId.updateDigest() + } + +- public fun connectToCompileService(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { +- val service = connectToService(compilerId, daemonOptions, errStream) +- if (service != null) { +- if (!checkId || checkCompilerId(service, compilerId, errStream)) { +- errStream.println(""[daemon client] found the suitable daemon"") +- return service +- } +- errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.mappers.flatMap { it.toArgs("""") }.joinToString("" "")) +- if (!autostart) return null; +- errStream.println(""[daemon client] shutdown the daemon"") +- service.shutdown() +- // TODO: find more reliable way +- Thread.sleep(1000) +- errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ val daemon = connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, DaemonReportingTargets(out = System.out), autostart = !clientOptions.stop, checkId = !clientOptions.stop) ++ ++ if (daemon == null) { ++ if (clientOptions.stop) { ++ System.err.println(""No daemon found to shut down"") + } +- else { +- if (!autostart) return null; +- else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ else throw Exception(""Unable to connect to daemon"") ++ } ++ else when { ++ clientOptions.stop -> { ++ println(""Shutdown the daemon"") ++ daemon.shutdown() ++ println(""Daemon shut down successfully"") + } ++ else -> { ++ println(""Executing daemon compilation with args: "" + filteredArgs.joinToString("" "")) ++ val outStrm = RemoteOutputStreamServer(System.out) ++ try { ++ val memBefore = daemon.getUsedMemory() / 1024 ++ val startTime = System.nanoTime() ++ ++ val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN, outStrm) + +- startDaemon(compilerId, daemonJVMOptions, daemonOptions, errStream) +- errStream.println(""[daemon client] daemon started, trying to connect"") +- return connectToService(compilerId, daemonOptions, errStream) ++ val endTime = System.nanoTime() ++ println(""Compilation result code: $res"") ++ val memAfter = daemon.getUsedMemory() / 1024 ++ println(""Compilation time: "" + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + "" ms"") ++ println(""Used memory $memAfter (${""%+d"".format(memAfter - memBefore)} kb)"") ++ } ++ finally { ++ outStrm.disconnect() ++ } ++ } + } ++ } + +- public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { +- KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, System.out, autostart = false, checkId = false) +- ?.shutdown() ++ // --- Implementation --------------------------------------- ++ ++ val verboseReporting = System.getProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY) != null ++ ++ fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String = ""daemon client"") { ++ if (category == DaemonReportCategory.DEBUG && !verboseReporting) return ++ out?.println(""[$source] ${category.name()}: $message"") ++ messages?.add(DaemonReportMessage(category, ""[$source] $message"")) ++ } ++ ++ private fun tryFindDaemon(registryDir: File, compilerId: CompilerId, reportingTargets: DaemonReportingTargets): CompileService? { ++ val classPathDigest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest() ++ val daemons = registryDir.walk() ++ .map { Pair(it, makeRunFilenameRegex(digest = classPathDigest, port = ""(\\d+)"").match(it.name)?.groups?.get(1)?.value?.toInt() ?: 0) } ++ .filter { it.second != 0 } ++ .map { ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""found suitable daemon on port ${it.second}, trying to connect"") ++ val daemon = tryConnectToDaemon(it.second, reportingTargets) ++ // cleaning orphaned file; note: daemon should shut itself down if it detects that the run file is deleted ++ if (daemon == null && !it.first.delete()) { ++ reportingTargets.report(DaemonReportCategory.INFO, ""WARNING: unable to delete seemingly orphaned file '${it.first.absolutePath}', cleanup recommended"") ++ } ++ daemon ++ } ++ .filterNotNull() ++ .toList() ++ return when (daemons.size()) { ++ 0 -> null ++ 1 -> daemons.first() ++ else -> throw IllegalStateException(""Multiple daemons serving the same compiler, reset with the cleanup required"") ++ // TODO: consider implementing automatic recovery instead, e.g. getting the youngest or least used daemon and shut down others + } ++ } + +- public fun shutdownCompileService(): Unit { +- shutdownCompileService(DaemonOptions()) ++ private fun tryConnectToDaemon(port: Int, reportingTargets: DaemonReportingTargets): CompileService? { ++ try { ++ val daemon = LocateRegistry.getRegistry(loopbackAddrName, port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${daemon.javaClass}"") ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, ""daemon not found"") ++ } ++ catch (e: ConnectException) { ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, ""cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below + } ++ return null ++ } + +- public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { + +- val outStrm = RemoteOutputStreamServer(out) +- try { +- return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN) +- } +- finally { +- outStrm.disconnect() +- } ++ private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, reportingTargets: DaemonReportingTargets) { ++ val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { ++ val javaw = File(it, ""javaw.exe"") ++ // TODO: doesn't seem reliable enough, consider more checks if OS is of windows flavor, etc. ++ if (javaw.exists() && javaw.isFile && javaw.canExecute()) javaw else File(it, ""java"") + } ++ val args = listOf(javaExecutable.absolutePath, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonJVMOptions.mappers.flatMap { it.toArgs(""-"") } + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + ++ compilerId.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() + +- public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ var isEchoRead = Semaphore(1) ++ isEchoRead.acquire() + +- val outStrm = RemoteOutputStreamServer(out) +- val cacheServers = hashMapOf() +- try { +- caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer( it.getValue()) }) +- return compiler.remoteIncrementalCompile(args, cacheServers, outStrm, CompileService.OutputFormat.XML) ++ val stdoutThread = ++ thread { ++ daemon.inputStream ++ .reader() ++ .forEachLine { ++ if (daemonOptions.runFilesPath.isNotEmpty() && it.contains(daemonOptions.runFilesPath)) { ++ isEchoRead.release() ++ return@forEachLine ++ } ++ reportingTargets.report(DaemonReportCategory.DEBUG, it, ""daemon"") ++ } ++ } ++ try { ++ // trying to wait for process ++ val daemonStartupTimeout = System.getProperty(COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY)?.let { ++ try { ++ it.toLong() ++ } ++ catch (e: Exception) { ++ reportingTargets.report(DaemonReportCategory.INFO, ""unable to interpret $COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms"") ++ null ++ } ++ } ?: DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ++ if (daemonOptions.runFilesPath.isNotEmpty()) { ++ val succeeded = isEchoRead.tryAcquire(daemonStartupTimeout, TimeUnit.MILLISECONDS) ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (!succeeded) ++ throw Exception(""Unable to get response from daemon in $daemonStartupTimeout ms"") + } +- finally { +- cacheServers.forEach { it.getValue().disconnect() } +- outStrm.disconnect() ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(daemonStartupTimeout) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdoutThread.isAlive) { ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ stdoutThread.stop() + } + } ++ } + +- data class ClientOptions( +- public var stop: Boolean = false +- ) : OptionsGroup { +- override val mappers: List> +- get() = listOf( BoolPropMapper(this, ::stop)) +- } + +- jvmStatic public fun main(vararg args: String) { +- val compilerId = CompilerId() +- val daemonOptions = DaemonOptions() +- val daemonLaunchingOptions = DaemonJVMOptions() +- val clientOptions = ClientOptions() +- val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) +- +- if (!clientOptions.stop) { +- if (compilerId.compilerClasspath.none()) { +- // attempt to find compiler to use +- println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") +- System.getProperty(""java.class.path"") +- ?.split(File.pathSeparator) +- ?.map { File(it).parent } +- ?.distinct() +- ?.map { +- it?.walk() +- ?.firstOrNull { it.getName().equals(COMPILER_JAR_NAME, ignoreCase = true) } +- } +- ?.filterNotNull() +- ?.firstOrNull() +- ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } +- } +- if (compilerId.compilerClasspath.none()) +- throw IllegalArgumentException(""Cannot find compiler jar"") +- else +- println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) ++ private fun checkCompilerId(compiler: CompileService, localId: CompilerId): Boolean { ++ val remoteId = compiler.getCompilerId() ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } + +- compilerId.updateDigest() ++ ++ class FileBasedLock(compilerId: CompilerId, daemonOptions: DaemonOptions) { ++ private val lockFile: File = ++ File(daemonOptions.runFilesPath,","do we need to keep them in home dir? can we use tempdir instead to eliminate possible issues caused by NFS-backed homedir, etc ? +",2015-09-08 17:58:11 +467,"@@ -18,246 +18,376 @@ package org.jetbrains.kotlin.rmi.kotlinr + + import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache + import org.jetbrains.kotlin.rmi.* +-import java.io.File +-import java.io.OutputStream +-import java.io.PrintStream ++import java.io.* + import java.rmi.ConnectException +-import java.rmi.Remote + import java.rmi.registry.LocateRegistry + import java.util.concurrent.Semaphore + import java.util.concurrent.TimeUnit + import kotlin.concurrent.thread + +-fun Process.isAlive() = ++ ++public object KotlinCompilerClient { ++ ++ val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3 ++ ++ ++ // TODO: remove jvmStatic after all use sites will switch to kotlin ++ jvmStatic ++ public fun connectToCompileService(compilerId: CompilerId, ++ daemonJVMOptions: DaemonJVMOptions, ++ daemonOptions: DaemonOptions, ++ reportingTargets: DaemonReportingTargets, ++ autostart: Boolean = true, ++ checkId: Boolean = true ++ ): CompileService? { ++ ++ var attempts = 0 ++ var fileLock: FileBasedLock? = null + try { +- this.exitValue() +- false ++ while (attempts++ < DAEMON_CONNECT_CYCLE_ATTEMPTS) { ++ val service = tryFindDaemon(File(daemonOptions.runFilesPath), compilerId, reportingTargets) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId)) { ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""connected to the daemon"") ++ return service ++ } ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""compiler identity don't match: "" + compilerId.mappers.flatMap { it.toArgs("""") }.joinToString("" "")) ++ if (!autostart) return null ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""daemon shut down correctly, restarting search"") ++ } ++ else { ++ if (!autostart) return null ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""no suitable daemon found, starting a new one"") ++ } ++ ++ if (fileLock == null || !fileLock.isLocked()) { ++ File(daemonOptions.runFilesPath).mkdirs() ++ fileLock = FileBasedLock(compilerId, daemonOptions) ++ // need to check the daemons again here, because of possible racing conditions ++ // note: the algorithm could be simpler if we'll acquire lock right from the beginning, but it may be costly ++ attempts-- ++ } ++ else { ++ startDaemon(compilerId, daemonJVMOptions, daemonOptions, reportingTargets) ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""daemon started, trying to resolve"") ++ } ++ } + } +- catch (e: IllegalThreadStateException) { +- true ++ catch (e: Exception) { ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, e.toString()) ++ } ++ finally { ++ fileLock?.release() + } ++ return null ++ } + +-public class KotlinCompilerClient { + +- companion object { ++ public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, DaemonReportingTargets(out = System.out), autostart = false, checkId = false) ++ ?.shutdown() ++ } + +- val DAEMON_STARTUP_TIMEOUT_MS = 10000L + +- private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ public fun shutdownCompileService(): Unit { ++ shutdownCompileService(DaemonOptions()) ++ } + +- val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running +- return compilerObj as? CompileService ?: +- throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ ++ public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ try { ++ return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN, outStrm) + } ++ finally { ++ outStrm.disconnect() ++ } ++ } + +- private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { +- try { +- val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) +- ?.lookup(COMPILER_SERVICE_RMI_NAME) +- if (daemon != null) +- return daemon +- errStream.println(""[daemon client] daemon not found"") +- } +- catch (e: ConnectException) { +- errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) +- // ignoring it - processing below +- } +- return null ++ ++ // TODO: remove jvmStatic after all use sites will switch to kotlin ++ jvmStatic ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, compilerOut: OutputStream, daemonOut: OutputStream): Int { ++ ++ val compilerOutStreamServer = RemoteOutputStreamServer(compilerOut) ++ val daemonOutStreamServer = RemoteOutputStreamServer(daemonOut) ++ val cacheServers = hashMapOf() ++ try { ++ caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer(it.getValue()) }) ++ return compiler.remoteIncrementalCompile(args, cacheServers, compilerOutStreamServer, CompileService.OutputFormat.XML, daemonOutStreamServer) ++ } ++ finally { ++ cacheServers.forEach { it.getValue().disconnect() } ++ compilerOutStreamServer.disconnect() ++ daemonOutStreamServer.disconnect() + } ++ } + + +- private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { +- val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { +- val javaw = File(it, ""javaw.exe"") +- if (javaw.exists()) javaw +- else File(it, ""java"") +- } +- // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs +- val args = listOf(javaExecutable.absolutePath, +- ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + +- daemonJVMOptions.mappers.flatMap { it.toArgs(""-"") } + +- COMPILER_DAEMON_CLASS_FQN + +- daemonOptions.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + +- compilerId.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } +- errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) +- val processBuilder = ProcessBuilder(args).redirectErrorStream(true) +- // assuming daemon process is deaf and (mostly) silent, so do not handle streams +- val daemon = processBuilder.start() +- +- var isEchoRead = Semaphore(1) +- isEchoRead.acquire() +- +- val stdoutThread = +- thread { +- daemon.getInputStream() +- .reader() +- .forEachLine { +- if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) { +- isEchoRead.release() +- return@forEachLine +- } +- errStream.println(""[daemon] "" + it) +- } +- } +- try { +- // trying to wait for process +- if (daemonOptions.startEcho.isNotEmpty()) { +- errStream.println(""[daemon client] waiting for daemon to respond"") +- val succeeded = isEchoRead.tryAcquire(DAEMON_STARTUP_TIMEOUT_MS, TimeUnit.MILLISECONDS) +- if (!daemon.isAlive()) +- throw Exception(""Daemon terminated unexpectedly"") +- if (!succeeded) +- throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") +- } +- else +- // without startEcho defined waiting for max timeout +- Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) +- } +- finally { +- // assuming that all important output is already done, the rest should be routed to the log by the daemon itself +- if (stdoutThread.isAlive) +- // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream +- stdoutThread.stop() ++ data class ClientOptions( ++ public var stop: Boolean = false ++ ) : OptionsGroup { ++ override val mappers: List> ++ get() = listOf(BoolPropMapper(this, ::stop)) ++ } ++ ++ ++ jvmStatic public fun main(vararg args: String) { ++ val compilerId = CompilerId() ++ val daemonOptions = DaemonOptions() ++ val daemonLaunchingOptions = DaemonJVMOptions() ++ val clientOptions = ClientOptions() ++ val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) ++ ++ if (!clientOptions.stop) { ++ if (compilerId.compilerClasspath.none()) { ++ // attempt to find compiler to use ++ System.err.println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") ++ System.getProperty(""java.class.path"") ++ ?.split(File.pathSeparator) ++ ?.map { File(it).parentFile } ++ ?.distinct() ++ ?.map { ++ it?.walk() ++ ?.firstOrNull { it.name.equals(COMPILER_JAR_NAME, ignoreCase = true) } ++ } ++ ?.filterNotNull() ++ ?.firstOrNull() ++ ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } + } +- } ++ if (compilerId.compilerClasspath.none()) ++ throw IllegalArgumentException(""Cannot find compiler jar"") ++ else ++ println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) + +- public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { +- val remoteId = compiler.getCompilerId() +- errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) +- errStream.println(""[daemon client] localId = "" + localId.toString()) +- return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && +- (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && +- (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ compilerId.updateDigest() + } + +- public fun connectToCompileService(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { +- val service = connectToService(compilerId, daemonOptions, errStream) +- if (service != null) { +- if (!checkId || checkCompilerId(service, compilerId, errStream)) { +- errStream.println(""[daemon client] found the suitable daemon"") +- return service +- } +- errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.mappers.flatMap { it.toArgs("""") }.joinToString("" "")) +- if (!autostart) return null; +- errStream.println(""[daemon client] shutdown the daemon"") +- service.shutdown() +- // TODO: find more reliable way +- Thread.sleep(1000) +- errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ val daemon = connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, DaemonReportingTargets(out = System.out), autostart = !clientOptions.stop, checkId = !clientOptions.stop) ++ ++ if (daemon == null) { ++ if (clientOptions.stop) { ++ System.err.println(""No daemon found to shut down"") + } +- else { +- if (!autostart) return null; +- else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ else throw Exception(""Unable to connect to daemon"") ++ } ++ else when { ++ clientOptions.stop -> { ++ println(""Shutdown the daemon"") ++ daemon.shutdown() ++ println(""Daemon shut down successfully"") + } ++ else -> { ++ println(""Executing daemon compilation with args: "" + filteredArgs.joinToString("" "")) ++ val outStrm = RemoteOutputStreamServer(System.out) ++ try { ++ val memBefore = daemon.getUsedMemory() / 1024 ++ val startTime = System.nanoTime() ++ ++ val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN, outStrm) + +- startDaemon(compilerId, daemonJVMOptions, daemonOptions, errStream) +- errStream.println(""[daemon client] daemon started, trying to connect"") +- return connectToService(compilerId, daemonOptions, errStream) ++ val endTime = System.nanoTime() ++ println(""Compilation result code: $res"") ++ val memAfter = daemon.getUsedMemory() / 1024 ++ println(""Compilation time: "" + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + "" ms"") ++ println(""Used memory $memAfter (${""%+d"".format(memAfter - memBefore)} kb)"") ++ } ++ finally { ++ outStrm.disconnect() ++ } ++ } + } ++ } + +- public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { +- KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, System.out, autostart = false, checkId = false) +- ?.shutdown() ++ // --- Implementation --------------------------------------- ++ ++ val verboseReporting = System.getProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY) != null ++ ++ fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String = ""daemon client"") { ++ if (category == DaemonReportCategory.DEBUG && !verboseReporting) return ++ out?.println(""[$source] ${category.name()}: $message"") ++ messages?.add(DaemonReportMessage(category, ""[$source] $message"")) ++ } ++ ++ private fun tryFindDaemon(registryDir: File, compilerId: CompilerId, reportingTargets: DaemonReportingTargets): CompileService? { ++ val classPathDigest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest() ++ val daemons = registryDir.walk() ++ .map { Pair(it, makeRunFilenameRegex(digest = classPathDigest, port = ""(\\d+)"").match(it.name)?.groups?.get(1)?.value?.toInt() ?: 0) } ++ .filter { it.second != 0 } ++ .map { ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""found suitable daemon on port ${it.second}, trying to connect"") ++ val daemon = tryConnectToDaemon(it.second, reportingTargets) ++ // cleaning orphaned file; note: daemon should shut itself down if it detects that the run file is deleted ++ if (daemon == null && !it.first.delete()) { ++ reportingTargets.report(DaemonReportCategory.INFO, ""WARNING: unable to delete seemingly orphaned file '${it.first.absolutePath}', cleanup recommended"") ++ } ++ daemon ++ } ++ .filterNotNull() ++ .toList() ++ return when (daemons.size()) { ++ 0 -> null ++ 1 -> daemons.first() ++ else -> throw IllegalStateException(""Multiple daemons serving the same compiler, reset with the cleanup required"") ++ // TODO: consider implementing automatic recovery instead, e.g. getting the youngest or least used daemon and shut down others + } ++ } + +- public fun shutdownCompileService(): Unit { +- shutdownCompileService(DaemonOptions()) ++ private fun tryConnectToDaemon(port: Int, reportingTargets: DaemonReportingTargets): CompileService? { ++ try { ++ val daemon = LocateRegistry.getRegistry(loopbackAddrName, port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${daemon.javaClass}"") ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, ""daemon not found"") ++ } ++ catch (e: ConnectException) { ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, ""cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below + } ++ return null ++ } + +- public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { + +- val outStrm = RemoteOutputStreamServer(out) +- try { +- return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN) +- } +- finally { +- outStrm.disconnect() +- } ++ private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, reportingTargets: DaemonReportingTargets) { ++ val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { ++ val javaw = File(it, ""javaw.exe"") ++ // TODO: doesn't seem reliable enough, consider more checks if OS is of windows flavor, etc. ++ if (javaw.exists() && javaw.isFile && javaw.canExecute()) javaw else File(it, ""java"") + } ++ val args = listOf(javaExecutable.absolutePath, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonJVMOptions.mappers.flatMap { it.toArgs(""-"") } + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + ++ compilerId.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() + +- public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ var isEchoRead = Semaphore(1) ++ isEchoRead.acquire() + +- val outStrm = RemoteOutputStreamServer(out) +- val cacheServers = hashMapOf() +- try { +- caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer( it.getValue()) }) +- return compiler.remoteIncrementalCompile(args, cacheServers, outStrm, CompileService.OutputFormat.XML) ++ val stdoutThread = ++ thread { ++ daemon.inputStream ++ .reader() ++ .forEachLine { ++ if (daemonOptions.runFilesPath.isNotEmpty() && it.contains(daemonOptions.runFilesPath)) { ++ isEchoRead.release() ++ return@forEachLine ++ } ++ reportingTargets.report(DaemonReportCategory.DEBUG, it, ""daemon"") ++ } ++ } ++ try { ++ // trying to wait for process ++ val daemonStartupTimeout = System.getProperty(COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY)?.let { ++ try { ++ it.toLong() ++ } ++ catch (e: Exception) { ++ reportingTargets.report(DaemonReportCategory.INFO, ""unable to interpret $COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms"") ++ null ++ } ++ } ?: DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ++ if (daemonOptions.runFilesPath.isNotEmpty()) { ++ val succeeded = isEchoRead.tryAcquire(daemonStartupTimeout, TimeUnit.MILLISECONDS) ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (!succeeded) ++ throw Exception(""Unable to get response from daemon in $daemonStartupTimeout ms"") + } +- finally { +- cacheServers.forEach { it.getValue().disconnect() } +- outStrm.disconnect() ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(daemonStartupTimeout) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdoutThread.isAlive) { ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ stdoutThread.stop() + } + } ++ } + +- data class ClientOptions( +- public var stop: Boolean = false +- ) : OptionsGroup { +- override val mappers: List> +- get() = listOf( BoolPropMapper(this, ::stop)) +- } + +- jvmStatic public fun main(vararg args: String) { +- val compilerId = CompilerId() +- val daemonOptions = DaemonOptions() +- val daemonLaunchingOptions = DaemonJVMOptions() +- val clientOptions = ClientOptions() +- val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) +- +- if (!clientOptions.stop) { +- if (compilerId.compilerClasspath.none()) { +- // attempt to find compiler to use +- println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") +- System.getProperty(""java.class.path"") +- ?.split(File.pathSeparator) +- ?.map { File(it).parent } +- ?.distinct() +- ?.map { +- it?.walk() +- ?.firstOrNull { it.getName().equals(COMPILER_JAR_NAME, ignoreCase = true) } +- } +- ?.filterNotNull() +- ?.firstOrNull() +- ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } +- } +- if (compilerId.compilerClasspath.none()) +- throw IllegalArgumentException(""Cannot find compiler jar"") +- else +- println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) ++ private fun checkCompilerId(compiler: CompileService, localId: CompilerId): Boolean { ++ val remoteId = compiler.getCompilerId() ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } + +- compilerId.updateDigest() ++ ++ class FileBasedLock(compilerId: CompilerId, daemonOptions: DaemonOptions) { ++ private val lockFile: File = ++ File(daemonOptions.runFilesPath, ++ makeRunFilenameString(ts = ""lock"", ++ digest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest(), ++ port = ""0"")) ++ ++ private var locked: Boolean = acquireLockFile(lockFile) ++ ++ public fun isLocked(): Boolean = locked ++ ++ synchronized public fun release(): Unit { ++ if (locked) { ++ lock?.release() ++ channel?.close() ++ lockFile.delete() ++ locked = false + } ++ } + +- val daemon = connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, System.out, autostart = !clientOptions.stop, checkId = !clientOptions.stop) ++ private val channel = if (locked) RandomAccessFile(lockFile, ""rw"").channel else null ++ private val lock = channel?.lock() + +- if (daemon == null) { +- if (clientOptions.stop) println(""No daemon found to shut down"") +- else throw Exception(""Unable to connect to daemon"") ++ synchronized private fun acquireLockFile(lockFile: File): Boolean {","~~Why do we have `:Boolean` function that always returns `true` ?~~ +I see, sorry +",2015-09-08 18:01:00 +468,"@@ -18,246 +18,376 @@ package org.jetbrains.kotlin.rmi.kotlinr + + import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache + import org.jetbrains.kotlin.rmi.* +-import java.io.File +-import java.io.OutputStream +-import java.io.PrintStream ++import java.io.* + import java.rmi.ConnectException +-import java.rmi.Remote + import java.rmi.registry.LocateRegistry + import java.util.concurrent.Semaphore + import java.util.concurrent.TimeUnit + import kotlin.concurrent.thread + +-fun Process.isAlive() = ++ ++public object KotlinCompilerClient { ++ ++ val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L ++ val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3 ++ ++ ++ // TODO: remove jvmStatic after all use sites will switch to kotlin ++ jvmStatic ++ public fun connectToCompileService(compilerId: CompilerId, ++ daemonJVMOptions: DaemonJVMOptions, ++ daemonOptions: DaemonOptions, ++ reportingTargets: DaemonReportingTargets, ++ autostart: Boolean = true, ++ checkId: Boolean = true ++ ): CompileService? { ++ ++ var attempts = 0 ++ var fileLock: FileBasedLock? = null + try { +- this.exitValue() +- false ++ while (attempts++ < DAEMON_CONNECT_CYCLE_ATTEMPTS) { ++ val service = tryFindDaemon(File(daemonOptions.runFilesPath), compilerId, reportingTargets) ++ if (service != null) { ++ if (!checkId || checkCompilerId(service, compilerId)) { ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""connected to the daemon"") ++ return service ++ } ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""compiler identity don't match: "" + compilerId.mappers.flatMap { it.toArgs("""") }.joinToString("" "")) ++ if (!autostart) return null ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""shutdown the daemon"") ++ service.shutdown() ++ // TODO: find more reliable way ++ Thread.sleep(1000) ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""daemon shut down correctly, restarting search"") ++ } ++ else { ++ if (!autostart) return null ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""no suitable daemon found, starting a new one"") ++ } ++ ++ if (fileLock == null || !fileLock.isLocked()) { ++ File(daemonOptions.runFilesPath).mkdirs() ++ fileLock = FileBasedLock(compilerId, daemonOptions) ++ // need to check the daemons again here, because of possible racing conditions ++ // note: the algorithm could be simpler if we'll acquire lock right from the beginning, but it may be costly ++ attempts-- ++ } ++ else { ++ startDaemon(compilerId, daemonJVMOptions, daemonOptions, reportingTargets) ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""daemon started, trying to resolve"") ++ } ++ } + } +- catch (e: IllegalThreadStateException) { +- true ++ catch (e: Exception) { ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, e.toString()) ++ } ++ finally { ++ fileLock?.release() + } ++ return null ++ } + +-public class KotlinCompilerClient { + +- companion object { ++ public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { ++ KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, DaemonReportingTargets(out = System.out), autostart = false, checkId = false) ++ ?.shutdown() ++ } + +- val DAEMON_STARTUP_TIMEOUT_MS = 10000L + +- private fun connectToService(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): CompileService? { ++ public fun shutdownCompileService(): Unit { ++ shutdownCompileService(DaemonOptions()) ++ } + +- val compilerObj = connectToDaemon(compilerId, daemonOptions, errStream) ?: return null // no registry - no daemon running +- return compilerObj as? CompileService ?: +- throw ClassCastException(""Unable to cast compiler service, actual class received: ${compilerObj.javaClass}"") ++ ++ public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { ++ ++ val outStrm = RemoteOutputStreamServer(out) ++ try { ++ return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN, outStrm) + } ++ finally { ++ outStrm.disconnect() ++ } ++ } + +- private fun connectToDaemon(compilerId: CompilerId, daemonOptions: DaemonOptions, errStream: PrintStream): Remote? { +- try { +- val daemon = LocateRegistry.getRegistry(""localhost"", daemonOptions.port) +- ?.lookup(COMPILER_SERVICE_RMI_NAME) +- if (daemon != null) +- return daemon +- errStream.println(""[daemon client] daemon not found"") +- } +- catch (e: ConnectException) { +- errStream.println(""[daemon client] cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) +- // ignoring it - processing below +- } +- return null ++ ++ // TODO: remove jvmStatic after all use sites will switch to kotlin ++ jvmStatic ++ public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, compilerOut: OutputStream, daemonOut: OutputStream): Int { ++ ++ val compilerOutStreamServer = RemoteOutputStreamServer(compilerOut) ++ val daemonOutStreamServer = RemoteOutputStreamServer(daemonOut) ++ val cacheServers = hashMapOf() ++ try { ++ caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer(it.getValue()) }) ++ return compiler.remoteIncrementalCompile(args, cacheServers, compilerOutStreamServer, CompileService.OutputFormat.XML, daemonOutStreamServer) ++ } ++ finally { ++ cacheServers.forEach { it.getValue().disconnect() } ++ compilerOutStreamServer.disconnect() ++ daemonOutStreamServer.disconnect() + } ++ } + + +- private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream) { +- val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { +- val javaw = File(it, ""javaw.exe"") +- if (javaw.exists()) javaw +- else File(it, ""java"") +- } +- // TODO: add some specific environment variables to the cp and may be command line, to allow some specific startup configs +- val args = listOf(javaExecutable.absolutePath, +- ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + +- daemonJVMOptions.mappers.flatMap { it.toArgs(""-"") } + +- COMPILER_DAEMON_CLASS_FQN + +- daemonOptions.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + +- compilerId.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } +- errStream.println(""[daemon client] starting the daemon as: "" + args.joinToString("" "")) +- val processBuilder = ProcessBuilder(args).redirectErrorStream(true) +- // assuming daemon process is deaf and (mostly) silent, so do not handle streams +- val daemon = processBuilder.start() +- +- var isEchoRead = Semaphore(1) +- isEchoRead.acquire() +- +- val stdoutThread = +- thread { +- daemon.getInputStream() +- .reader() +- .forEachLine { +- if (daemonOptions.startEcho.isNotEmpty() && it.contains(daemonOptions.startEcho)) { +- isEchoRead.release() +- return@forEachLine +- } +- errStream.println(""[daemon] "" + it) +- } +- } +- try { +- // trying to wait for process +- if (daemonOptions.startEcho.isNotEmpty()) { +- errStream.println(""[daemon client] waiting for daemon to respond"") +- val succeeded = isEchoRead.tryAcquire(DAEMON_STARTUP_TIMEOUT_MS, TimeUnit.MILLISECONDS) +- if (!daemon.isAlive()) +- throw Exception(""Daemon terminated unexpectedly"") +- if (!succeeded) +- throw Exception(""Unable to get response from daemon in $DAEMON_STARTUP_TIMEOUT_MS ms"") +- } +- else +- // without startEcho defined waiting for max timeout +- Thread.sleep(DAEMON_STARTUP_TIMEOUT_MS) +- } +- finally { +- // assuming that all important output is already done, the rest should be routed to the log by the daemon itself +- if (stdoutThread.isAlive) +- // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream +- stdoutThread.stop() ++ data class ClientOptions( ++ public var stop: Boolean = false ++ ) : OptionsGroup { ++ override val mappers: List> ++ get() = listOf(BoolPropMapper(this, ::stop)) ++ } ++ ++ ++ jvmStatic public fun main(vararg args: String) { ++ val compilerId = CompilerId() ++ val daemonOptions = DaemonOptions() ++ val daemonLaunchingOptions = DaemonJVMOptions() ++ val clientOptions = ClientOptions() ++ val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) ++ ++ if (!clientOptions.stop) { ++ if (compilerId.compilerClasspath.none()) { ++ // attempt to find compiler to use ++ System.err.println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") ++ System.getProperty(""java.class.path"") ++ ?.split(File.pathSeparator) ++ ?.map { File(it).parentFile } ++ ?.distinct() ++ ?.map { ++ it?.walk() ++ ?.firstOrNull { it.name.equals(COMPILER_JAR_NAME, ignoreCase = true) } ++ } ++ ?.filterNotNull() ++ ?.firstOrNull() ++ ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } + } +- } ++ if (compilerId.compilerClasspath.none()) ++ throw IllegalArgumentException(""Cannot find compiler jar"") ++ else ++ println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) + +- public fun checkCompilerId(compiler: CompileService, localId: CompilerId, errStream: PrintStream): Boolean { +- val remoteId = compiler.getCompilerId() +- errStream.println(""[daemon client] remoteId = "" + remoteId.toString()) +- errStream.println(""[daemon client] localId = "" + localId.toString()) +- return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && +- (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && +- (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ compilerId.updateDigest() + } + +- public fun connectToCompileService(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, errStream: PrintStream, autostart: Boolean = true, checkId: Boolean = true): CompileService? { +- val service = connectToService(compilerId, daemonOptions, errStream) +- if (service != null) { +- if (!checkId || checkCompilerId(service, compilerId, errStream)) { +- errStream.println(""[daemon client] found the suitable daemon"") +- return service +- } +- errStream.println(""[daemon client] compiler identity don't match: "" + compilerId.mappers.flatMap { it.toArgs("""") }.joinToString("" "")) +- if (!autostart) return null; +- errStream.println(""[daemon client] shutdown the daemon"") +- service.shutdown() +- // TODO: find more reliable way +- Thread.sleep(1000) +- errStream.println(""[daemon client] daemon shut down correctly, restarting"") ++ val daemon = connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, DaemonReportingTargets(out = System.out), autostart = !clientOptions.stop, checkId = !clientOptions.stop) ++ ++ if (daemon == null) { ++ if (clientOptions.stop) { ++ System.err.println(""No daemon found to shut down"") + } +- else { +- if (!autostart) return null; +- else errStream.println(""[daemon client] cannot connect to Compile Daemon, trying to start"") ++ else throw Exception(""Unable to connect to daemon"") ++ } ++ else when { ++ clientOptions.stop -> { ++ println(""Shutdown the daemon"") ++ daemon.shutdown() ++ println(""Daemon shut down successfully"") + } ++ else -> { ++ println(""Executing daemon compilation with args: "" + filteredArgs.joinToString("" "")) ++ val outStrm = RemoteOutputStreamServer(System.out) ++ try { ++ val memBefore = daemon.getUsedMemory() / 1024 ++ val startTime = System.nanoTime() ++ ++ val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN, outStrm) + +- startDaemon(compilerId, daemonJVMOptions, daemonOptions, errStream) +- errStream.println(""[daemon client] daemon started, trying to connect"") +- return connectToService(compilerId, daemonOptions, errStream) ++ val endTime = System.nanoTime() ++ println(""Compilation result code: $res"") ++ val memAfter = daemon.getUsedMemory() / 1024 ++ println(""Compilation time: "" + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + "" ms"") ++ println(""Used memory $memAfter (${""%+d"".format(memAfter - memBefore)} kb)"") ++ } ++ finally { ++ outStrm.disconnect() ++ } ++ } + } ++ } + +- public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit { +- KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, System.out, autostart = false, checkId = false) +- ?.shutdown() ++ // --- Implementation --------------------------------------- ++ ++ val verboseReporting = System.getProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY) != null ++ ++ fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String = ""daemon client"") { ++ if (category == DaemonReportCategory.DEBUG && !verboseReporting) return ++ out?.println(""[$source] ${category.name()}: $message"") ++ messages?.add(DaemonReportMessage(category, ""[$source] $message"")) ++ } ++ ++ private fun tryFindDaemon(registryDir: File, compilerId: CompilerId, reportingTargets: DaemonReportingTargets): CompileService? { ++ val classPathDigest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest() ++ val daemons = registryDir.walk() ++ .map { Pair(it, makeRunFilenameRegex(digest = classPathDigest, port = ""(\\d+)"").match(it.name)?.groups?.get(1)?.value?.toInt() ?: 0) } ++ .filter { it.second != 0 } ++ .map { ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""found suitable daemon on port ${it.second}, trying to connect"") ++ val daemon = tryConnectToDaemon(it.second, reportingTargets) ++ // cleaning orphaned file; note: daemon should shut itself down if it detects that the run file is deleted ++ if (daemon == null && !it.first.delete()) { ++ reportingTargets.report(DaemonReportCategory.INFO, ""WARNING: unable to delete seemingly orphaned file '${it.first.absolutePath}', cleanup recommended"") ++ } ++ daemon ++ } ++ .filterNotNull() ++ .toList() ++ return when (daemons.size()) { ++ 0 -> null ++ 1 -> daemons.first() ++ else -> throw IllegalStateException(""Multiple daemons serving the same compiler, reset with the cleanup required"") ++ // TODO: consider implementing automatic recovery instead, e.g. getting the youngest or least used daemon and shut down others + } ++ } + +- public fun shutdownCompileService(): Unit { +- shutdownCompileService(DaemonOptions()) ++ private fun tryConnectToDaemon(port: Int, reportingTargets: DaemonReportingTargets): CompileService? { ++ try { ++ val daemon = LocateRegistry.getRegistry(loopbackAddrName, port) ++ ?.lookup(COMPILER_SERVICE_RMI_NAME) ++ if (daemon != null) ++ return daemon as? CompileService ?: ++ throw ClassCastException(""Unable to cast compiler service, actual class received: ${daemon.javaClass}"") ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, ""daemon not found"") ++ } ++ catch (e: ConnectException) { ++ reportingTargets.report(DaemonReportCategory.EXCEPTION, ""cannot connect to registry: "" + (e.getCause()?.getMessage() ?: e.getMessage() ?: ""unknown exception"")) ++ // ignoring it - processing below + } ++ return null ++ } + +- public fun compile(compiler: CompileService, args: Array, out: OutputStream): Int { + +- val outStrm = RemoteOutputStreamServer(out) +- try { +- return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN) +- } +- finally { +- outStrm.disconnect() +- } ++ private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, reportingTargets: DaemonReportingTargets) { ++ val javaExecutable = File(System.getProperty(""java.home""), ""bin"").let { ++ val javaw = File(it, ""javaw.exe"") ++ // TODO: doesn't seem reliable enough, consider more checks if OS is of windows flavor, etc. ++ if (javaw.exists() && javaw.isFile && javaw.canExecute()) javaw else File(it, ""java"") + } ++ val args = listOf(javaExecutable.absolutePath, ++ ""-cp"", compilerId.compilerClasspath.joinToString(File.pathSeparator)) + ++ daemonJVMOptions.mappers.flatMap { it.toArgs(""-"") } + ++ COMPILER_DAEMON_CLASS_FQN + ++ daemonOptions.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } + ++ compilerId.mappers.flatMap { it.toArgs(COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) } ++ reportingTargets.report(DaemonReportCategory.DEBUG, ""starting the daemon as: "" + args.joinToString("" "")) ++ val processBuilder = ProcessBuilder(args).redirectErrorStream(true) ++ // assuming daemon process is deaf and (mostly) silent, so do not handle streams ++ val daemon = processBuilder.start() + +- public fun incrementalCompile(compiler: CompileService, args: Array, caches: Map, out: OutputStream): Int { ++ var isEchoRead = Semaphore(1) ++ isEchoRead.acquire() + +- val outStrm = RemoteOutputStreamServer(out) +- val cacheServers = hashMapOf() +- try { +- caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer( it.getValue()) }) +- return compiler.remoteIncrementalCompile(args, cacheServers, outStrm, CompileService.OutputFormat.XML) ++ val stdoutThread = ++ thread { ++ daemon.inputStream ++ .reader() ++ .forEachLine { ++ if (daemonOptions.runFilesPath.isNotEmpty() && it.contains(daemonOptions.runFilesPath)) { ++ isEchoRead.release() ++ return@forEachLine ++ } ++ reportingTargets.report(DaemonReportCategory.DEBUG, it, ""daemon"") ++ } ++ } ++ try { ++ // trying to wait for process ++ val daemonStartupTimeout = System.getProperty(COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY)?.let { ++ try { ++ it.toLong() ++ } ++ catch (e: Exception) { ++ reportingTargets.report(DaemonReportCategory.INFO, ""unable to interpret $COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms"") ++ null ++ } ++ } ?: DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ++ if (daemonOptions.runFilesPath.isNotEmpty()) { ++ val succeeded = isEchoRead.tryAcquire(daemonStartupTimeout, TimeUnit.MILLISECONDS) ++ if (!daemon.isAlive()) ++ throw Exception(""Daemon terminated unexpectedly"") ++ if (!succeeded) ++ throw Exception(""Unable to get response from daemon in $daemonStartupTimeout ms"") + } +- finally { +- cacheServers.forEach { it.getValue().disconnect() } +- outStrm.disconnect() ++ else ++ // without startEcho defined waiting for max timeout ++ Thread.sleep(daemonStartupTimeout) ++ } ++ finally { ++ // assuming that all important output is already done, the rest should be routed to the log by the daemon itself ++ if (stdoutThread.isAlive) { ++ // TODO: find better method to stop the thread, but seems it will require asynchronous consuming of the stream ++ stdoutThread.stop() + } + } ++ } + +- data class ClientOptions( +- public var stop: Boolean = false +- ) : OptionsGroup { +- override val mappers: List> +- get() = listOf( BoolPropMapper(this, ::stop)) +- } + +- jvmStatic public fun main(vararg args: String) { +- val compilerId = CompilerId() +- val daemonOptions = DaemonOptions() +- val daemonLaunchingOptions = DaemonJVMOptions() +- val clientOptions = ClientOptions() +- val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX) +- +- if (!clientOptions.stop) { +- if (compilerId.compilerClasspath.none()) { +- // attempt to find compiler to use +- println(""compiler wasn't explicitly specified, attempt to find appropriate jar"") +- System.getProperty(""java.class.path"") +- ?.split(File.pathSeparator) +- ?.map { File(it).parent } +- ?.distinct() +- ?.map { +- it?.walk() +- ?.firstOrNull { it.getName().equals(COMPILER_JAR_NAME, ignoreCase = true) } +- } +- ?.filterNotNull() +- ?.firstOrNull() +- ?.let { compilerId.compilerClasspath = listOf(it.absolutePath) } +- } +- if (compilerId.compilerClasspath.none()) +- throw IllegalArgumentException(""Cannot find compiler jar"") +- else +- println(""desired compiler classpath: "" + compilerId.compilerClasspath.joinToString(File.pathSeparator)) ++ private fun checkCompilerId(compiler: CompileService, localId: CompilerId): Boolean { ++ val remoteId = compiler.getCompilerId() ++ return (localId.compilerVersion.isEmpty() || localId.compilerVersion == remoteId.compilerVersion) && ++ (localId.compilerClasspath.all { remoteId.compilerClasspath.contains(it) }) && ++ (localId.compilerDigest.isEmpty() || remoteId.compilerDigest.isEmpty() || localId.compilerDigest == remoteId.compilerDigest) ++ } + +- compilerId.updateDigest() ++ ++ class FileBasedLock(compilerId: CompilerId, daemonOptions: DaemonOptions) { ++ private val lockFile: File = ++ File(daemonOptions.runFilesPath, ++ makeRunFilenameString(ts = ""lock"", ++ digest = compilerId.compilerClasspath.map { File(it).absolutePath }.distinctStringsDigest(), ++ port = ""0"")) ++ ++ private var locked: Boolean = acquireLockFile(lockFile) ++ ++ public fun isLocked(): Boolean = locked ++ ++ synchronized public fun release(): Unit { ++ if (locked) { ++ lock?.release() ++ channel?.close() ++ lockFile.delete() ++ locked = false + } ++ } + +- val daemon = connectToCompileService(compilerId, daemonLaunchingOptions, daemonOptions, System.out, autostart = !clientOptions.stop, checkId = !clientOptions.stop) ++ private val channel = if (locked) RandomAccessFile(lockFile, ""rw"").channel else null ++ private val lock = channel?.lock() + +- if (daemon == null) { +- if (clientOptions.stop) println(""No daemon found to shut down"") +- else throw Exception(""Unable to connect to daemon"") ++ synchronized private fun acquireLockFile(lockFile: File): Boolean { ++ if (lockFile.createNewFile()) return true ++ try { ++ // attempt to delete if file is orphaned ++ if (lockFile.delete() && lockFile.createNewFile()) ++ return true // if orphaned file deleted assuming that the probability of + } +- else when { +- clientOptions.stop -> { +- println(""Shutdown the daemon"") +- daemon.shutdown() +- println(""Daemon shut down successfully"") +- } +- else -> { +- println(""Executing daemon compilation with args: "" + filteredArgs.joinToString("" "")) +- val outStrm = RemoteOutputStreamServer(System.out) +- try { +- val memBefore = daemon.getUsedMemory() / 1024 +- val startTime = System.nanoTime() +- val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN) +- val endTime = System.nanoTime() +- println(""Compilation result code: $res"") +- val memAfter = daemon.getUsedMemory() / 1024 +- println(""Compilation time: "" + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + "" ms"") +- println(""Used memory $memAfter (${""%+d"".format(memAfter - memBefore)} kb)"") +- } +- finally { +- outStrm.disconnect() +- } +- } ++ catch (e: IOException) { ++ // Ignoring it - assuming it is another client process owning it + } ++ var attempts = 0L ++ while (lockFile.exists() && attempts++ * COMPILE_DAEMON_STARTUP_LOCK_TIMEOUT_CHECK_MS < COMPILE_DAEMON_STARTUP_LOCK_TIMEOUT_MS) { ++ Thread.sleep(COMPILE_DAEMON_STARTUP_LOCK_TIMEOUT_CHECK_MS) ++ } ++ if (lockFile.exists()) ++ throw IOException(""Timeout waiting the release of the lock file '${lockFile.absolutePath}"") ++ ++ return lockFile.createNewFile()","Can't we replace it with something like that: + +``` kotlin +do { + if (lockFile.createNewFile()) return true + Thread.sleep(...) +} while (!timeout) + +throw timeout exception +``` + +It is better because the function has only two cases: return or exception. Now we have true/false/exception +",2015-09-08 18:05:15 +403,"@@ -18,64 +18,89 @@ package org.jetbrains.kotlin.gradle.plugin + + import org.gradle.BuildAdapter + import org.gradle.BuildResult ++import org.gradle.api.invocation.Gradle + import org.gradle.api.logging.Logging + import java.lang.ref.Reference + import java.util.concurrent.ScheduledExecutorService ++import kotlin.text.MatchGroup + +-class FinishBuildListener(var pluginClassLoader: ParentLastURLClassLoader?) : BuildAdapter() { ++internal fun getUsedMemoryKb(): Long { ++ System.gc() ++ val rt = Runtime.getRuntime() ++ return (rt.totalMemory() - rt.freeMemory()) / 1024 ++} ++ ++ ++private fun comparableVersionStr(version: String) = ++ ""(\\d+)\\.(\\d+).*"" ++ .toRegex() ++ .match(version) ++ ?.groups ++ ?.drop(1)?.take(2) ++ // checking if two subexpression groups are found and length of each is >0 and <4 ++ ?.let { if (it.all { (it?.value?.length() ?: 0).let { it > 0 && it < 4 }}) it else null } ++ ?.map { ""%3s"".format(it?.value ?: 0).replace(' ', '0') } ++ ?.joinToString(""."")","We can omit some of safe calls using `filterNotNull` and `padStart` trick: + +``` kotlin +private fun comparableVersionStr(version: String) = + ""(\\d+)\\.(\\d+).*"" + .toRegex() + .match(version) + ?.groups + ?.drop(1)?.take(2) + ?.filterNotNull() + // checking if two subexpression groups are found and length of each is >0 and <4 + ?.let { if (it.size() == 2 && it.all { it.value.length() in 1..3 }) it else null } + ?.map { it.value.padStart(3, '0') } + ?.joinToString(""."") +``` +",2015-07-29 13:33:34 +336,"@@ -18,72 +18,118 @@ + + package kotlin + ++/** A function that takes 0 arguments. */ + public trait Function0 { ++ /** Invokes the function with the specified arguments. */","no arguments +",2015-03-12 14:49:28 +337,"@@ -18,72 +18,118 @@ + + package kotlin + ++/** A function that takes 0 arguments. */ + public trait Function0 { ++ /** Invokes the function with the specified arguments. */ + public fun invoke(): R + } ++/** A function that takes 1 arguments. */","plural use for 1 +",2015-03-12 14:49:50 +335,"@@ -18,72 +18,118 @@ + + package kotlin + ++/** An extension function that takes 0 arguments. */ + public trait ExtensionFunction0 { ++ /** Invokes the function with the specified arguments. */","There are no arguments, so just ""Invokes the function"" +",2015-03-12 14:48:48 +334,"@@ -18,72 +18,118 @@ + + package kotlin + ++/** An extension function that takes 0 arguments. */ + public trait ExtensionFunction0 { ++ /** Invokes the function with the specified arguments. */ + public fun T.invoke(): R + } ++/** An extension function that takes 1 arguments. */","""argument"", no ""s"" +",2015-03-12 14:48:29 +696,"@@ -181,7 +183,7 @@ object TopDownAnalyzerFacadeForJVM { + // TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport + val container = createContainerForTopDownAnalyzerForJvm( + moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker, +- partProvider, moduleClassResolver, jvmTarget, languageVersionSettings ++ partProvider, moduleClassResolver, jvmTarget, languageVersionSettings, useJavac",Not to this PR but just to note: this TODO above should be handled somehow,2017-04-05 12:26:58 +633,"@@ -1839,6 +1844,14 @@ + language=""kotlin"" + /> + ++ BooleanArray.groupByTo(result: MutableMap {","You can simplify this code by changing the return type to `Sequence` and using `generateSequence()` +",2016-09-05 17:29:17 +692,"@@ -186,6 +187,14 @@ class K2JVMCompiler : CLICompiler() { + val environment = createEnvironmentWithScriptingSupport(rootDisposable, configuration, arguments, messageCollector) + ?: return COMPILATION_ERROR + ++ if (arguments.useJavac) {",Looks like this if / else is better to be moved above (just before environment definition). It's more consistent with previous code.,2017-04-05 11:27:20 +691,"@@ -186,6 +187,14 @@ class K2JVMCompiler : CLICompiler() { + val environment = createEnvironmentWithScriptingSupport(rootDisposable, configuration, arguments, messageCollector) + ?: return COMPILATION_ERROR + ++ if (arguments.useJavac) { ++ environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true) ++ environment.registerJavac(outDir = File(destination), ++ messageCollector = messageCollector, ++ arguments = arguments.javacArguments) ++ } ++ else environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, false)",Use {} here,2017-04-05 11:23:54 +878,"@@ -187,5 +185,26 @@ fun arrays(): List { + } + } + ++ templates add f(""nullIfEmpty()"") { ++ only(ArraysOfObjects, ArraysOfPrimitives, Collections) ++ doc { f -> ++ """""" ++ Returns `this` value if it is not empty or `null`, if it is. ++ ++ ${if (f == ArraysOfObjects || f == ArraysOfPrimitives) ++ ""@sample samples.collections.Arrays.nullIfEmpty"" ++ else if (f == Collections) ++ ""@sample samples.collections.Collections.nullIfEmpty"" ++ else ++ """" ++ } ++ """""" ++ } ++ returns(""SELF?"") ++ body { ++ ""return if (this == null || this.isEmpty()) null else this""","`this == null` +^ expression is always false",2017-07-03 18:19:57 +290,"@@ -1893,7 +1893,7 @@ public inline fun String.lastOrNull(predicate: (Char) -> Boolean): Char? { + } + + /** +- * Returns single element, or throws exception if there is no or more than one element ++ * Returns the single element, or throws an exception if if the collection is empty or has more than one element.","if if +",2015-02-09 15:49:12 +321,"@@ -19,18 +19,39 @@ package kotlin.jvm + import java.lang.annotation.Retention + import java.lang.annotation.RetentionPolicy + ++/** ++ * Marks the JVM backing field of the annotated property as `volatile`, meaning that it can ++ * be modified asynchronously by concurrently running threads.","""can be modified async"" is strange wording. Even if field is not volatile, you still can modify it async by concurrent threads, but effect may be different. Need better description. +",2015-02-11 08:41:43 +510,"@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen + import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor + import org.jetbrains.kotlin.psi.KtExpression + import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall ++import org.jetbrains.kotlin.codegen.binding.CodegenBinding.*","Unused import +",2016-02-09 08:33:51 +992,"@@ -195,6 +195,7 @@ enum class TraversalOrder { + BACKWARD + } + ++",Remove me,2017-08-16 09:42:12 +753,"@@ -195,6 +205,11 @@ class K2JVMCompiler : CLICompiler() { + } + + KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment) ++ ++ if (arguments.useJavac) { ++ val success = JavacWrapper.getInstance(environment.project).use(JavacWrapper::compile) ++ if (!success) return COMPILATION_ERROR ++ }",And this code should also be performed for previous branches,2017-04-11 09:57:39 +464,"@@ -198,6 +202,8 @@ + + + ++ ++ ","Other lines here use `` +",2015-09-01 07:28:05 +89,"@@ -199,6 +199,22 @@ public inline fun Array.groupByTo(result: MutableMap Array.indexOf(item : T) : Int {","We usually don't add space before colon in parameters list +",2013-12-26 20:29:36 +90,"@@ -199,6 +199,22 @@ public inline fun Array.groupByTo(result: MutableMap Array.indexOf(item : T) : Int { ++ if (item == null) {","Why do you need to handle 'item==null' case separately? '==' operator works properly with nulls. +",2013-12-26 20:30:31 +91,"@@ -199,6 +199,22 @@ public inline fun Array.groupByTo(result: MutableMap Array.indexOf(item : T) : Int { ++ if (item == null) { ++ for (i in 0..size - 1) if (this[i] == null) {","size-1 can be replaced by lastIndex. +",2013-12-26 20:31:11 +340,"@@ -2,36 +2,65 @@ package kotlin.concurrent + + import java.util.concurrent.* + ++/** ++ * Return the current thread.","Returns +",2015-03-12 14:56:56 +917,"@@ -20,6 +20,15 @@ package kotlin.script.dependencies + + import java.io.File + ++// discuss ++ ++// Currently File is used to disambiguate between plain strings and paths ++// One of the ideas is to use java.nio.Path but this requires JDK 7 ++// that means that script templates would require higher JDK (but since script are run by calling koltinc it seems ok to me after consideration)",I think requiring JDK 8 in scripts is fine,2017-07-25 10:15:27 +915,"@@ -20,6 +20,15 @@ package kotlin.script.dependencies + + import java.io.File + ++// discuss ++ ++// Currently File is used to disambiguate between plain strings and paths ++// One of the ideas is to use java.nio.Path but this requires JDK 7 ++// that means that script templates would require higher JDK (but since script are run by calling koltinc it seems ok to me after consideration) ++// Andrey expressed the idea that File (or Path) does not support other protocols, should we use URL/URI? (is it viable to support non-file protocols in compiler and IDE?)","> File (or Path) does not support other protocols + +Path _does_ support other protocols AFAIK. You can create a custom `java.nio.file.FileSystem` and resolve paths within that file system.",2017-07-25 10:08:01 +931,"@@ -20,6 +20,15 @@ package kotlin.script.dependencies + + import java.io.File + ++// discuss ++ ++// Currently File is used to disambiguate between plain strings and paths ++// One of the ideas is to use java.nio.Path but this requires JDK 7 ++// that means that script templates would require higher JDK (but since script are run by calling koltinc it seems ok to me after consideration) ++// Andrey expressed the idea that File (or Path) does not support other protocols, should we use URL/URI? (is it viable to support non-file protocols in compiler and IDE?) ++// ++// Explicitly references javaHome, what if it's not a jvm targeted script? ++// Currently it's convenient for IDE code and for the user because including jdk classes in classpath is a mess + data class ScriptDependencies(",What's the difference between `sources` and `scripts`?,2017-07-25 12:57:27 +929,"@@ -20,6 +20,15 @@ package kotlin.script.dependencies + + import java.io.File + ++// discuss ++ ++// Currently File is used to disambiguate between plain strings and paths ++// One of the ideas is to use java.nio.Path but this requires JDK 7 ++// that means that script templates would require higher JDK (but since script are run by calling koltinc it seems ok to me after consideration) ++// Andrey expressed the idea that File (or Path) does not support other protocols, should we use URL/URI? (is it viable to support non-file protocols in compiler and IDE?) ++// ++// Explicitly references javaHome, what if it's not a jvm targeted script? ++// Currently it's convenient for IDE code and for the user because including jdk classes in classpath is a mess + data class ScriptDependencies( + val javaHome: File? = null,","What is `javaHome`: is it required to be a path to the JDK, or a path to the JRE is enough?",2017-07-25 11:50:16 +930,"@@ -20,6 +20,15 @@ package kotlin.script.dependencies + + import java.io.File + ++// discuss ++ ++// Currently File is used to disambiguate between plain strings and paths ++// One of the ideas is to use java.nio.Path but this requires JDK 7 ++// that means that script templates would require higher JDK (but since script are run by calling koltinc it seems ok to me after consideration) ++// Andrey expressed the idea that File (or Path) does not support other protocols, should we use URL/URI? (is it viable to support non-file protocols in compiler and IDE?) ++// ++// Explicitly references javaHome, what if it's not a jvm targeted script? ++// Currently it's convenient for IDE code and for the user because including jdk classes in classpath is a mess + data class ScriptDependencies( + val javaHome: File? = null, + val classpath: List = emptyList(),","Can we use here directories/jars/individual files? +Maybe it's worth to document it somewhere",2017-07-25 12:48:24 +22,"@@ -200,4 +201,13 @@ public static PsiElement createPrimaryConstructor(Project project) { + JetClass aClass = createClass(project, ""class A()""); + return aClass.findElementAt(7).getParent(); + } ++ ++ public static JetSimpleNameExpression createClassLabel(Project project, @NotNull String labelName) { ++ JetThisExpression expression = (JetThisExpression) createExpression(project, ""this@"" + labelName); ++ return expression.getTargetLabel(); ++ } ++ ++ public static JetExpression createFieldIdentifier(Project project, @NotNull String fieldName) { ++ return createExpression(project, ""$"" + fieldName); ++ }","Maybe this one will be final :) +",2013-01-11 16:42:26 +21,"@@ -200,4 +202,14 @@ public static PsiElement createPrimaryConstructor(Project project) { + JetClass aClass = createClass(project, ""class A()""); + return aClass.findElementAt(7).getParent(); + } ++ ++ public static PsiElement createClassLabel(Project project, @NotNull String labelName) { ++ JetExpression expression = createExpression(project, ""this@"" + labelName); ++ return expression.getLastChild();","However I have one question: in current variant org.jetbrains.jet.JetNodeTypes#LABEL_QUALIFIER returned - this is normal that org.jetbrains.jet.lexer.JetTokens#FIELD_IDENTIFIER replaced by org.jetbrains.jet.JetNodeTypes#LABEL_QUALIFIER? +",2013-01-11 16:27:42 +20,"@@ -200,4 +202,14 @@ public static PsiElement createPrimaryConstructor(Project project) { + JetClass aClass = createClass(project, ""class A()""); + return aClass.findElementAt(7).getParent(); + } ++ ++ public static PsiElement createClassLabel(Project project, @NotNull String labelName) { ++ JetExpression expression = createExpression(project, ""this@"" + labelName); ++ return expression.getLastChild(); ++ } ++ ++ public static PsiElement createFieldIdentifier(Project project, @NotNull String fieldName) { ++ JetExpression expression = createExpression(project, ""$"" + fieldName); ++ return expression.getFirstChild();","Much nice +",2013-01-11 16:21:10 +18,"@@ -200,4 +202,19 @@ public static PsiElement createPrimaryConstructor(Project project) { + JetClass aClass = createClass(project, ""class A()""); + return aClass.findElementAt(7).getParent(); + } ++ ++ public static PsiElement createClassLabel(Project project, @NotNull String labelName) { ++ final String labelTemplate = ""class {0}()'{' fun aFun()'{' this@{0}'}'}""; ++ JetClass aClass = createClass(project, MessageFormat.format(labelTemplate, labelName)); ++ final int offset = 18; // @labelName ++ return aClass.getBody().findElementAt(offset); ++ } ++ ++ public static PsiElement createFieldIdentifier(Project project, @NotNull String fieldName){ ++ final String labelTemplate = ""class aClass()'{'var {0}:Int=0;set(value)'{'${0}'} '}""; ++ JetClass aClass = createClass(project, MessageFormat.format(labelTemplate, fieldName)); ++ final JetDeclaration declaration = aClass.getBody().getDeclarations().get(0); ++ final int offset = 11; // $fieldName ++ return declaration.getLastChild().findElementAt(offset);","Ok, now it looks better +",2013-01-11 15:01:40 +305,"@@ -205,7 +241,9 @@ public inline fun Map.filterValues(predicate: (V) -> Boolean): Map< + + + /** +- * Appends all elements matching the given *predicate* into the given *destination* ++ * Appends all entries matching the given [predicate] into the given [destination] mutable map.","""[destination] mutable map."", looks confusing a bit. +",2015-02-09 16:08:37 +487,"@@ -209,7 +209,7 @@ public void generateMethod( + generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen); + } + else if (staticInCompanionObject) { +- // native platformStatic foo() in companion object should delegate to the static native function moved to the outer class ++ // native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class + mv.visitCode(); + FunctionDescriptor staticFunctionDescriptor = PlatformStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);","rename `PlatformStaticGenerator` -> `JvmStaticGenerator`? +",2015-10-30 15:12:17 +299,"@@ -21,15 +21,18 @@ private object EmptyMap : Map { + /** Returns an empty read-only map of specified type */ + public fun emptyMap(): Map = EmptyMap as Map + +-/** Returns a new read-only map of given pairs, where the first value is the key, and the second is value */ ++/** ++ * Returns a new read-only map with the specified contents, given as a list of pairs ++ * where the first value is the key and the second is the value. ++ */","specify, that it behaves as sequential `put` calls, so that if conflicting keys exist in source sequence, last one wins. +",2015-02-09 16:01:42 +754,"@@ -21,17 +21,30 @@ import com.intellij.psi.search.GlobalSearchScope + import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol + import org.jetbrains.kotlin.cli.jvm.index.JavaRoot + import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl ++import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass + import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder + import org.jetbrains.kotlin.name.ClassId + import org.jetbrains.kotlin.name.FqName + import org.jetbrains.kotlin.name.Name + import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment ++import org.jetbrains.kotlin.wrappers.trees.computeClassId + import java.io.InputStream + + class CliVirtualFileFinder( + private val index: JvmDependenciesIndex, + private val scope: GlobalSearchScope + ) : VirtualFileFinder() { ++ ++ override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? { ++ if (javaClass !is JavaClassImpl) { ++ return javaClass.computeClassId()?.let(this::findKotlinClass) ?: return null",This `return null` is unnecessary,2017-04-11 09:58:37 +773,"@@ -21,17 +21,31 @@ import com.intellij.psi.search.GlobalSearchScope + import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol + import org.jetbrains.kotlin.cli.jvm.index.JavaRoot + import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex ++import org.jetbrains.kotlin.load.java.structure.JavaClass ++import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl ++import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass ++import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass + import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder + import org.jetbrains.kotlin.name.ClassId + import org.jetbrains.kotlin.name.FqName + import org.jetbrains.kotlin.name.Name + import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment ++import org.jetbrains.kotlin.wrappers.trees.computeClassId + import java.io.InputStream + + class CliVirtualFileFinder( + private val index: JvmDependenciesIndex, + private val scope: GlobalSearchScope + ) : VirtualFileFinder() { ++ ++ override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? { ++ if (javaClass !is JavaClassImpl && javaClass !is BinaryJavaClass) { ++ return javaClass.computeClassId()?.let(this::findKotlinClass)",I think you should create a custom KotlinJvmBinaryClass implementation here: there's no need to look up the class that is already found and passed in the argument,2017-04-25 07:34:22 +684,"@@ -21,5 +21,6 @@ + + + ++ ","Try to avoid light classes, some explanation below",2017-01-25 12:51:11 +916,"@@ -21,6 +21,24 @@ package kotlin.script.dependencies + import java.io.File + import kotlin.script.dependencies.DependenciesResolver.ResolveResult + ++//discuss ++ ++// Provides api to discover dependencies of scripts ++// Dependencies can be content-dependent ++// ++// Some concerns on naming: ++// Environment -> ScriptEnvironment (top level class with too common a name) ++// ResolveResult -> ResolutionResult",+1 for ResolutionResult,2017-07-25 10:13:47 +932,"@@ -21,6 +21,24 @@ package kotlin.script.dependencies + import java.io.File + import kotlin.script.dependencies.DependenciesResolver.ResolveResult + ++//discuss ++ ++// Provides api to discover dependencies of scripts ++// Dependencies can be content-dependent ++// ++// Some concerns on naming: ++// Environment -> ScriptEnvironment (top level class with too common a name) ++// ResolveResult -> ResolutionResult ++// ++// Admittedly DependenciesResolver is too generic a name, but ScriptDependenciesResolver is already taken by deprecated interface ++// My guess is script.runtime.jar is not gonna be used as application wide dependency in users project (like stdlib) ++// but rather as a dependency for a module that contains DependenciesResolver implementation so maybe this is a non-problem ++// ++// ResolveResult contains resulting dependencies and reports (diagnostics?) ++// reports may contain errors (regardless of result being Success or Failure) which is gonna lead to compiler error and script not run/error highlighting in IDE. ++// Is this semantic reasonable? Are Success and Failure misleading names? ++// Main idea behind Failure is to be able to distinguish between scenarios where resolver could or could not return meaningful ScriptDependencies object. ++// For example, IDE can avoid repainting all external references as errors when Resolver threw an exception or is in inconsistent state. + typealias Environment = Map + + interface DependenciesResolver : @Suppress(""DEPRECATION"") ScriptDependenciesResolver {",`DependencyResolver` instead of `DependenciesResolver`,2017-07-26 01:48:17 +779,"@@ -211,6 +220,25 @@ class K2JVMCompiler : CLICompiler() { + } + } + ++ private fun registerJavacIfNeeded(environment: KotlinCoreEnvironment, ++ arguments: K2JVMCompilerArguments, ++ messageCollector: MessageCollector) { ++ if (arguments.useJavac) { ++ environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true) ++ environment.registerJavac(messageCollector = messageCollector, ++ arguments = arguments.javacArguments) ++ } else { ++ environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, false)",There's no need to put `false` as the configuration value if you're using `getBoolean` at call sites,2017-04-25 07:58:25 +867,"@@ -212,11 +212,12 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing + afterInside(LT, TYPE_ARGUMENT_LIST).spaces(0) + beforeInside(GT, TYPE_ARGUMENT_LIST).spaces(0) + +- betweenInside(FOR_KEYWORD, LPAR, FOR).spacing(1, 1, 0, false, 0) +- betweenInside(IF_KEYWORD, LPAR, IF).spacing(1, 1, 0, false, 0) +- betweenInside(WHILE_KEYWORD, LPAR, WHILE).spacing(1, 1, 0, false, 0) +- betweenInside(WHILE_KEYWORD, LPAR, DO_WHILE).spacing(1, 1, 0, false, 0) +- betweenInside(WHEN_KEYWORD, LPAR, WHEN).spacing(1, 1, 0, false, 0) ++ betweenInside(FOR_KEYWORD, LPAR, FOR).lineBreakOrForceSpace(false, kotlinCommonSettings.SPACE_BEFORE_FOR_PARENTHESES)","There is never a line break in these locations, so you should better use `spaceIf`.",2017-06-02 15:50:02 +29,"@@ -214,21 +214,32 @@ public static void addTypeAnnotation(Project project, JetParameter parameter, @N + ReferenceToClassesShortening.compactReferenceToClasses(Collections.singletonList(parameter)); + } + +- private static void removeTypeAnnotation(@NotNull JetNamedDeclaration property, @Nullable JetTypeReference typeReference) { ++ private static void removeTypeAnnotation(@NotNull PsiElement removeAfter, @Nullable JetTypeReference typeReference) {","I don't love name 'removeAfter' but I didn't come up with anything better. +",2013-02-09 17:40:01 +880,"@@ -2165,6 +2183,9 @@ public fun Iterable.sum(): Int { + */ + @kotlin.jvm.JvmName(""sumOfLong"") + public fun Iterable.sum(): Long { ++ if (this is LongProgression) { ++ return (this.first + this.last) * this.count() / 2",Is this as overflow safe as the old approach? `(this.first + this.last) * this.count()` might overflow when `(this.first + this.last) * (this.count() / 2)` wouldn't.,2017-07-05 09:28:29 +307,"@@ -217,14 +255,16 @@ public inline fun > Map.filterTo(destination: C + } + + /** +- * Returns a map containing all key-value pairs matching the given *predicate* ++ * Returns a map containing all key-value pairs matching the given [predicate].","Returns a _new_ map +",2015-02-09 16:09:53 +774,"@@ -217,6 +216,34 @@ class KotlinCoreEnvironment private constructor( + project.registerService(VirtualFileFinderFactory::class.java, finderFactory) + } + ++ // Maybe there is another way to obtain all java files ++ private val VirtualFile.javaFiles: List","This is rather inefficient because it creates a lot of lists. Try something like this: +``` + private val VirtualFile.javaFiles: List + get() = mutableListOf().apply { + VfsUtilCore.processFilesRecursively(this@javaFiles) { file -> + if (file.fileType == JavaFileType.INSTANCE) { + add(file) + } + true + } + } +``` +",2017-04-25 07:44:49 +777,"@@ -217,6 +216,34 @@ class KotlinCoreEnvironment private constructor( + project.registerService(VirtualFileFinderFactory::class.java, finderFactory) + } + ++ // Maybe there is another way to obtain all java files ++ private val VirtualFile.javaFiles: List ++ get() = children.filter { it.extension == ""java"" } ++ .toMutableList() ++ .apply { ++ children ++ .filter(VirtualFile::isDirectory) ++ .forEach { dir -> addAll(dir.javaFiles) } ++ } ++ ++ private val javaFiles",`allJavaFiles` maybe?,2017-04-25 07:51:16 +775,"@@ -217,6 +216,34 @@ class KotlinCoreEnvironment private constructor( + project.registerService(VirtualFileFinderFactory::class.java, finderFactory) + } + ++ // Maybe there is another way to obtain all java files ++ private val VirtualFile.javaFiles: List ++ get() = children.filter { it.extension == ""java"" } ++ .toMutableList() ++ .apply { ++ children ++ .filter(VirtualFile::isDirectory) ++ .forEach { dir -> addAll(dir.javaFiles) } ++ } ++ ++ private val javaFiles ++ get() = configuration.kotlinSourceRoots ++ .mapNotNull(this::findLocalDirectory) ++ .flatMap { it.javaFiles } ++ .map { File(it.canonicalPath) } ++ ++ fun registerJavac(files: List = javaFiles, ++ kotlinFiles: List = sourceFiles, ++ messageCollector: MessageCollector? = null, ++ arguments: Array? = null) { ++ projectEnvironment.project.registerService(JavacWrapper::class.java, JavacWrapper(files,",Please fix formatting here,2017-04-25 07:46:06 +863,"@@ -2180,6 +2180,14 @@ + language=""kotlin"" + /> + ++ = NoDependencies::class, + val scriptFilePattern: String = DEFAULT_SCRIPT_FILE_PATTERN)","Do we need `scriptFilePattern` in this restricted form at all? +- IDE uses `ScriptTemplatesProvider.filePattern` that allows to determine scripts without loading script definition annotation. +- There might be scripts of different kind that differentiate by full path or maybe content.",2017-07-25 10:33:46 +928,"@@ -22,13 +22,28 @@ import kotlin.reflect.KClass + import kotlin.script.dependencies.DependenciesResolver.NoDependencies + import kotlin.script.dependencies.ScriptDependenciesResolver + ++// discuss ++ ++// One of the requests is to allow to share compiler args via script templates: https://youtrack.jetbrains.com/issue/KT-19120 ++// Making it a property of ScriptTemplateDefinition is a viable options but it doesn't allow to changes compiler arguments based on script content. ++// For example, it could be possible to allow file level annotation and use it like: ++// @file: ExtraCompilerArgs(""-enableWhatever"") ++ + const val DEFAULT_SCRIPT_FILE_PATTERN = "".*\\.kts"" + ++// classes annotated with ScriptTemplateDefinition become script templates. ++// examples: https://github.com/JetBrains/kotlin/blob/5faad493b4cf7bf33bf82475e966a99a8e835720/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt#L564-L601 + @Target(AnnotationTarget.CLASS) + @Retention(AnnotationRetention.RUNTIME) + annotation class ScriptTemplateDefinition(val resolver: KClass = NoDependencies::class, + val scriptFilePattern: String = DEFAULT_SCRIPT_FILE_PATTERN) + ++// usage example: https://github.com/JetBrains/kotlin/blob/88652154c96402475d42ae0496ab0b423cc0a2b2/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolve.kt#L42-L42","I'm confused, why is this needed? Can't the DependenciesResolver implementation just filter out the unneeded annotations from ScriptContents.annotations?",2017-07-25 11:43:48 +86,"@@ -22,3 +22,22 @@ class FinalClass() { + + private public class C + private public object D ++ ++class LegalModifiersInConstructorParameters(val a: Int, private var b: String, vararg v: Int) ++ ++class IllegalModifiersInConstructorParameters(private a: Int) ++ ++class SecondIllegalModifiersInConstructorParameters(public b: String) ++ ++class ThirdIllegalModifiersInConstructorParameters(protected vararg v: Int) ++ ++abstract class IllegalModifiersInFunctionParameters() { ++ ++ abstract fun illegalModifiersInFunctionParameters(public a: Int, vararg v: String) ++ ++ private fun illegalModifiersInCatchBlock() { ++ try { ++ ++ } catch (public e: Exception) {} ++ } ++}","You should add a test with annotation and modifier like +fun foo(deprecated(""ss"") public a: Int) +because annotations are parsed in modifier list. + +Also a test for more than one modifier on parameter is missed +",2013-08-29 10:28:29 +4,"@@ -22,5 +22,5 @@ + public class CompilerVersion { + // The value of this constant is generated by the build script + // DON'T MODIFY IT +- public static final String VERSION = ""@snapshot@""; ++ public static final String VERSION = ""snapshot"";","This will crash the build miserably. +",2012-05-15 18:34:55 +784,"@@ -22,6 +22,9 @@ + + + ++ ++ ",Do you know if it's possible to download sources of this artifact from somewhere? This would be very useful,2017-04-25 08:16:39 +97,"@@ -220,6 +220,7 @@ add.name.to.argument.single=Add name to argument\: ''{0}'' + add.name.to.argument.multiple=Add name to argument... + add.name.to.argument.action=Add name to argument... + add.name.to.parameter.name.chooser.title=Choose parameter name ++get.call.replacement=Get Call Replace","That's not a good name for an intention. The name should be ""Do something"", with correct capitalization. + +In such cases, always refer to existing UI elements, so the new features will be consistent with common style. +",2014-01-27 21:28:35 +6,"@@ -225,38 +225,7 @@","ignore this file +",2012-05-24 14:20:57 +111,"@@ -226,6 +226,10 @@ replace.with.dot.qualified.method.call.intention=Replace with simple method call + replace.with.dot.qualified.method.call.intention.family=Replace with simple method call + replace.with.infix.function.call.intention=Replace with infix function call + replace.with.infix.function.call.intention.family=Replace with infix function call ++remove.braces=Remove Braces ++remove.braces.family=Remove Braces ++add.braces=Add Braces ++add.braces.family=Add Braces","Capitalization of family name is correct, but of intention text is not. See other intentions as a reference. +",2014-02-21 16:36:51 +119,"@@ -226,6 +226,8 @@ replace.with.dot.qualified.method.call.intention=Replace with simple method call + replace.with.dot.qualified.method.call.intention.family=Replace with simple method call + replace.with.infix.function.call.intention=Replace with infix function call + replace.with.infix.function.call.intention.family=Replace with infix function call ++replace.with.operator.assign.intention=Replace with an operator-assign expression ++replace.with.operator.assign.intention.family=Replace with an operator-assign expression","By convention every significant word in the intention family name should be capitalized. Compare `unfold.assignment.to.when` and `unfold.assignment.to.when.family`, for example +",2014-02-25 14:48:13 +378,"@@ -227,7 +228,7 @@ private void checkForCastImpossibilityOrRedundancy( + expression.getLeft(), context.dataFlowInfo, actualType, context); + for (JetType possibleType : possibleTypes) { + if (typeChecker.isSubtypeOf(possibleType, targetType)) { +- context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression)); ++ context.trace.report(USELESS_CAST.on(expression));","Probably this shouldn't be reported at all here? + +Consider this example: + +``` +trait A +trait B +trait C : A, B + +fun foo(a: A) {} +fun foo(b: B) {} + +fun bar(c: C) = foo(c as A) // <-- incorrect warning here, the cast is not useless +``` +",2015-04-24 13:25:55 +882,"@@ -2278,6 +2278,14 @@ + language=""kotlin"" + /> + ++ ( +- KtParameterList::class.java, ""Add '@JvmOverloads' annotation"" ++class AddJvmOverloadsIntention : SelfTargetingIntention( ++ KtModifierListOwner::class.java, ""Add '@JvmOverloads' annotation"" + ), LowPriorityAction { + +- override fun isApplicableTo(element: KtParameterList, caretOffset: Int): Boolean { +- val parent = element.parent as? KtModifierListOwner ?: return false +- val target = when (parent) { +- is KtNamedFunction -> ""function '${parent.name}'"" +- is KtPrimaryConstructor -> ""primary constructor"" +- is KtSecondaryConstructor -> ""secondary constructor"" ++ override fun isApplicableTo(element: KtModifierListOwner, caretOffset: Int): Boolean { ++ val (targetName, parameterList) = when (element) { ++ is KtNamedFunction -> { ++ val funKeyword = element.funKeyword ?: return false ++ val valueParameterList = element.valueParameterList ?: return false ++ if (caretOffset !in funKeyword.startOffset..valueParameterList.endOffset) { ++ return false ++ } ++ ++ ""function '${element.name}'"" to valueParameterList ++ } ++ is KtSecondaryConstructor -> { ++ val constructorKeyword = element.getConstructorKeyword() ++ val valueParameterList = element.valueParameterList ?: return false ++ if (caretOffset !in constructorKeyword.startOffset..valueParameterList.endOffset) { ++ return false ++ } ++ ++ ""secondary constructor"" to valueParameterList ++ } ++ is KtPrimaryConstructor -> ""primary constructor"" to element.valueParameterList + else -> return false + } +- text = ""Add '@JvmOverloads' annotation to $target"" ++ val parameters = parameterList?.parameters ?: return false ++ ++ text = ""Add '@JvmOverloads' annotation to $targetName"" + + return !ProjectStructureUtil.isJsKotlinModule(element.getContainingKtFile()) +- && element.parameters.any { it.hasDefaultValue() } +- && parent.findAnnotation(annotationFqName) == null ++ && parameters.size > 1","This is not exactly the check that I meant. Specifically for the primary constructor, Kotlin will generate a no-argument overload when all arguments have default values, even if the @JvmOverloads annotation is not present. This doesn't happen for regular functions. +",2016-04-29 09:57:23 +517,"@@ -235,6 +235,22 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++operator fun List.get(indexesRange: IntRange): List = ++ if(indexesRange.first < 0 || indexesRange.last > lastIndex)","What is the value of `last` of empty range and of `lastIndex` of the empty list? Don't they throw an exception? You have to add corresponding tests +",2016-02-27 13:50:01 +519,"@@ -235,6 +235,22 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++operator fun List.get(indexesRange: IntRange): List = ++ if(indexesRange.first < 0 || indexesRange.last > lastIndex) ++ throw IndexOutOfBoundsException()","It should be more debug information: exact range bounds and the list size +",2016-02-27 13:52:37 +520,"@@ -235,6 +235,22 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++operator fun List.get(indexesRange: IntRange): List = ++ if(indexesRange.first < 0 || indexesRange.last > lastIndex) ++ throw IndexOutOfBoundsException() ++ else if(indexesRange.first<=indexesRange.last)","Formatting +",2016-02-27 13:52:52 +518,"@@ -235,6 +235,22 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++operator fun List.get(indexesRange: IntRange): List = ++ if(indexesRange.first < 0 || indexesRange.last > lastIndex) ++ throw IndexOutOfBoundsException() ++ else if(indexesRange.first<=indexesRange.last) ++ subList(indexesRange.first, indexesRange.last+1) ++ else ++ listOf() ++ ++/** ++ * Returns the list multiplication. ++ */ ++operator fun List.times(factor: Int): List = (1..factor).flatMap { this }","Negative `factor` should throw an exception +",2016-02-27 13:51:33 +525,"@@ -235,6 +235,28 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++operator fun List.get(indexesRange: IntRange): List = ++ if (indexesRange.first < 0) ++ throw IndexOutOfBoundsException(""Range beginning (${indexesRange.first}) is less than zero."") ++ else if (indexesRange.last > lastIndex) ++ throw IndexOutOfBoundsException(""Range end (${indexesRange.last}) is bigger then the end of table ($lastIndex)"") ++ else if (indexesRange.first <= indexesRange.last) ++ subList(indexesRange.first, indexesRange.last + 1)","It should be `toList()` after because we need a copy but `subList` just refers to the original list. +",2016-02-27 17:26:31 +524,"@@ -235,6 +235,28 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++operator fun List.get(indexesRange: IntRange): List = ++ if (indexesRange.first < 0) ++ throw IndexOutOfBoundsException(""Range beginning (${indexesRange.first}) is less than zero."") ++ else if (indexesRange.last > lastIndex) ++ throw IndexOutOfBoundsException(""Range end (${indexesRange.last}) is bigger then the end of table ($lastIndex)"") ++ else if (indexesRange.first <= indexesRange.last) ++ subList(indexesRange.first, indexesRange.last + 1) ++ else ++ listOf() ++ ++/** ++ * Returns the list multiplication. ++ */ ++operator fun List.times(factor: Int): List = ++ if (factor < 0) ++ throw ArithmeticException(""List factor must be bigger then 0"")","You may just do `require(factor >= 0) {""error message… ""}`. Also notice that in Java wrong arguments should cause `IllegalArgumentException` (so it is done inside of the `require` function) +",2016-02-27 17:24:54 +526,"@@ -235,6 +235,30 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++public operator fun List.get(indexesRange: IntRange): List = ++ if (indexesRange.isEmpty()) ++ listOf() ++ else if (indexesRange.first < 0) ++ throw IndexOutOfBoundsException(""Range beginning (${indexesRange.first}) is less than zero."") ++ else if (indexesRange.last > lastIndex) ++ throw IndexOutOfBoundsException(""Range end (${indexesRange.last}) is bigger then the end of table ($lastIndex)"")","typo: than +",2016-02-28 12:52:55 +527,"@@ -235,6 +235,30 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + } + + /** ++ * Returns the elements from the list from indexes specified in range. ++ */ ++public operator fun List.get(indexesRange: IntRange): List = ++ if (indexesRange.isEmpty()) ++ listOf() ++ else if (indexesRange.first < 0) ++ throw IndexOutOfBoundsException(""Range beginning (${indexesRange.first}) is less than zero."") ++ else if (indexesRange.last > lastIndex) ++ throw IndexOutOfBoundsException(""Range end (${indexesRange.last}) is bigger then the end of table ($lastIndex)"") ++ else if (indexesRange.first <= indexesRange.last) ++ subList(indexesRange.first, indexesRange.last + 1).toList() ++ else ++ throw Exception(""Unknown exception in getting range of indexes from list"") ++ ++/** ++ * Returns the list multiplication. ++ */ ++public operator fun List.times(factor: Int): List { ++ require(factor >= 0) { ""List factor must be bigger then 0"" }","Type: than +Also lets include actual value in the message +",2016-02-28 12:53:53 +306,"@@ -236,7 +276,7 @@ public inline fun > Map.filterNotTo(destination + } + + /** +- * Returns a map containing all key-value pairs matching the given *predicate* ++ * Returns a map containing all key-value pairs not matching the given [predicate].","Returns a _new_ map +",2015-02-09 16:09:41 +540,"@@ -237,24 +237,26 @@ public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, com + /** + * Returns the elements from the list from indexes specified in range. + */ +-operator fun List.get(indexesRange: IntRange): List = +- if (indexesRange.first < 0) ++public operator fun List.get(indexesRange: IntRange): List = ++ if (indexesRange.isEmpty()) ++ listOf() ++ else if (indexesRange.first < 0) + throw IndexOutOfBoundsException(""Range beginning (${indexesRange.first}) is less than zero."") + else if (indexesRange.last > lastIndex) + throw IndexOutOfBoundsException(""Range end (${indexesRange.last}) is bigger then the end of table ($lastIndex)"") + else if (indexesRange.first <= indexesRange.last) +- subList(indexesRange.first, indexesRange.last + 1) ++ subList(indexesRange.first, indexesRange.last + 1).toList() + else +- listOf() ++ throw Exception(""Unknown exception in getting range of indexes from list"") + + /** + * Returns the list multiplication. + */ +-operator fun List.times(factor: Int): List = +- if (factor < 0) +- throw ArithmeticException(""List factor must be bigger then 0"") +- else +- (1..factor).flatMap { this } ++public operator fun List.times(factor: Int): List { ++ require(factor >= 0) { ""List factor must be bigger then 0"" }","""than"", also is 0 itself valid or not? +",2016-04-21 07:24:05 +577,"@@ -24,11 +24,11 @@ internal fun Map.getOrImplicitDefault(key: K): V { + /** + * Returns a wrapper of this read-only map, having the implicit default value provided with the specified function [defaultValue]. + * This implicit default value is used when properties are delegated to the returned map, +- * and that map doesn't contain value for the key specified. ++ * and that map doesn't contain a value for the key specified. + * +- * When this map already have an implicit default value provided with a former call to [withDefault], it is being replaced by this call. ++ * When this map already has an implicit default value provided with a former call to [withDefault], it is being replaced by this call. + */ +-public fun Map.withDefault(defaultValue: (key: K) -> V): Map = ++fun Map.withDefault(defaultValue: (key: K) -> V): Map =","Missing `public` modifier. +",2016-06-07 14:34:38 +249,"@@ -24,19 +24,38 @@ import org.apache.commons.io.FileUtils + import org.jetbrains.kotlin.gradle.plugin.* + import org.gradle.api.Project + import org.jetbrains.jet.config.Services +- +-public open class KotlinCompile(): AbstractCompile() { +- ++import org.jetbrains.jet.cli.js.K2JSCompiler ++import org.jetbrains.jet.cli.common.arguments.K2JSCompilerArguments ++import org.jetbrains.k2js.config.MetaInfServices ++import org.jetbrains.k2js.config.ClassPathLibraryDefintionsConfig ++import org.jetbrains.jet.cli.common.CLIConfigurationKeys ++import org.jetbrains.jet.config.CompilerConfiguration ++import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil ++import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment ++import com.intellij.openapi.Disposable ++import com.intellij.openapi.util.Disposer ++import org.jetbrains.k2js.config.EcmaVersion ++import org.gradle.api.tasks.Copy ++import org.gradle.api.Action ++import org.gradle.api.internal.project.ProjectInternal ++import groovy.lang.Closure ++import org.codehaus.groovy.runtime.MethodClosure ++import org.gradle.api.DefaultTask ++import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments ++import org.jetbrains.jet.cli.common.CLICompiler ++ ++ ++abstract class AbstractKotlinCompile(): AbstractCompile() { + val srcDirsSources = HashSet() +- val compiler = K2JVMCompiler() ++ abstract protected val compiler: CLICompiler ++ abstract protected fun createBlankArgs(): T ++ public var kotlinOptions: T = createBlankArgs() ++ ++ public var kotlinDestinationDir : File? = getDestinationDir()","Unnecessary space before colon(`:`) +",2014-11-11 17:05:49 +393,"@@ -24,7 +24,7 @@ fileAnnotations + ; + + fileAnnotation +- : ""@"" ""file"" "":"" (""["" annotationEntry+ ""]"" | annotationEntry) ++ : ""@"" ""file"" "":"" (""["" annotation+ ""]"" | annotation)","I think it should be `unescapedAnnotation` instead of `annotation`. +Probably we should also remove `("":"" ""file"")?` part from `annotationPrefix`. +",2015-07-15 11:50:08 +995,"@@ -241,7 +241,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter { + } + val name = if (primitiveType != null) { + ""javaPrimitiveType"" +- } else { ++ } ++ else {",It is wrong according to Java Code Conventions,2017-08-16 15:39:44 +110,"@@ -244,7 +244,10 @@ + + + +- ++ ++ ","This should be reverted +",2014-02-21 16:35:27 +582,"@@ -245,10 +245,12 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() { + fun createCodeFragmentForLabeledObjects(project: Project, markupMap: Map<*, ValueMarkup>): Pair> { + val sb = StringBuilder() + val labeledObjects = HashMap() ++ val psiNameHelper = PsiNameHelper.getInstance(project) ++ + val entrySet: Set> = markupMap.entries + for ((value, markup) in entrySet) { + val labelName = markup.text +- if (!Name.isValidIdentifier(labelName)) continue ++ if (!Name.isValidIdentifier(labelName) || !psiNameHelper.isIdentifier(labelName)) continue","Do we need Name.isValidIdentifier() here at all? +",2016-07-15 13:48:52 +530,"@@ -246,4 +246,32 @@ private fun rangeCheck(size: Int, fromIndex: Int, toIndex: Int) { + } + } + ++/** ++ * List ""and"" operation that returns elements that are in both lists in number of lower list ++ * Note that listOf(1, 1) and listOf(1, 1, 1) == listOf(1, 1) ++ */ ++infix fun List.and(secList: List): List { ++ var tempSecList = secList ++ return filter { ++ if ( it in tempSecList ) { ++ tempSecList -= it ++ true ++ } else { ++ false ++ } ++ } ++} + ++/** ++ * List ""or"" operation that returns elements that are in both lists in number of lower list ++ * Note that listOf(1, 1) and listOf(1, 1, 1) == listOf(1, 1, 1)","listOf(1, 1) OR listOf(1, 1, 1) == listOf(1, 1, 1) !? +",2016-03-17 21:49:05 +485,"@@ -248,6 +250,18 @@ abstract class AbstractKotlinPlugin @Inject constructor(val scriptHandler: Scrip + } + }) + } ++ ++ private fun configureResolutionStrategy(project: Project) { ++ val projectVersion = loadKotlinVersionFromResource(project.logger) ++ project.configurations.all(Action { configuration -> ++ configuration.resolutionStrategy.eachDependency { details -> ++ val requested = details.requested ++ if (requested.group.equals(""org.jetbrains.kotlin"") && requested.version.isEmpty()) { ++ details.useTarget(""${requested.group}:${requested.name}:$projectVersion"")","Why do you put `project.version` here? shouldn't you somehow lookup Kotlin plugin version here? +",2015-10-28 13:06:10 +329,"@@ -25,65 +25,146 @@ package kotlin + public class Byte private () : Number, Comparable { + default object {} + ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public override fun compareTo(other: Byte): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Char): Int","Comparing byte with char for ordering probably requires more description about what it really means. +",2015-03-12 14:42:57 +330,"@@ -25,65 +25,146 @@ package kotlin + public class Byte private () : Number, Comparable { + default object {} + ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public override fun compareTo(other: Byte): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Char): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Short): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Int): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Long): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Float): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Double): Int + ++ /** Adds the two values. */ + public fun plus(other: Byte): Int ++ /** Adds the two values. */ + public fun plus(other: Char): Int ++ /** Adds the two values. */ + public fun plus(other: Short): Int ++ /** Adds the two values. */ + public fun plus(other: Int): Int ++ /** Adds the two values. */ + public fun plus(other: Long): Long ++ /** Adds the two values. */ + public fun plus(other: Float): Float ++ /** Adds the two values. */","""Adds the other value to this value."" +like in `minus` +",2015-03-12 14:43:35 +331,"@@ -25,65 +25,146 @@ package kotlin + public class Byte private () : Number, Comparable { + default object {} + ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public override fun compareTo(other: Byte): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Char): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Short): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Int): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Long): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Float): Int ++/** ++ * Compares this value with the specified value for order. ++ * Returns zero if this value is equal to the specified other value, a negative number if its less than other, ++ * or a positive number if its greater than other. ++ */ + public fun compareTo(other: Double): Int + ++ /** Adds the two values. */ + public fun plus(other: Byte): Int ++ /** Adds the two values. */ + public fun plus(other: Char): Int ++ /** Adds the two values. */ + public fun plus(other: Short): Int ++ /** Adds the two values. */ + public fun plus(other: Int): Int ++ /** Adds the two values. */ + public fun plus(other: Long): Long ++ /** Adds the two values. */ + public fun plus(other: Float): Float ++ /** Adds the two values. */ + public fun plus(other: Double): Double + ++ /** Subtracts the other value from this value. */ + public fun minus(other: Byte): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Char): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Short): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Int): Int ++ /** Subtracts the other value from this value. */ + public fun minus(other: Long): Long ++ /** Subtracts the other value from this value. */ + public fun minus(other: Float): Float ++ /** Subtracts the other value from this value. */ + public fun minus(other: Double): Double + ++ /** Multiplies the two values. */","Multiplies this value by the other value. +",2015-03-12 14:43:56 +971,"@@ -256,6 +255,16 @@ public KotlinType getBodyExpressionType( + DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo; + boolean jumpOutPossible = false; + for (Iterator iterator = block.iterator(); iterator.hasNext(); ) { ++ // Use filtering trace to keep effect system cache only for one statement","For me this place is not very clear, check it with @erokhins ",2017-08-15 16:02:59 +491,"@@ -257,7 +258,7 @@ public class KotlinCoreEnvironment private constructor( + val appEnv = getOrCreateApplicationEnvironmentForProduction(configuration, configFilePaths) + // Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally + // breaks a lot of tests, therefore it is disabled for production and enabled for tests +- if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY) == null) { ++ if (!(System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY).toBooleanLenient() ?: false)) {","This could be written as + +``` +if (KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.systemPropertyAsBooleanOrTrueOtherwise(negate = true)) { +``` +",2015-11-27 18:21:30 +267,"@@ -264,3 +264,35 @@ public fun Iterable>.toMap(): Map { + * Converts this [Map] to a [LinkedHashMap] so future insertion orders are maintained + */ + public fun Map.toLinkedMap(): MutableMap = LinkedHashMap(this) ++ ++/** ++ * Create a new read-only map from a map and a single new key-value pair ++ */ ++public fun Map.plus(pair: Pair): Map { ++ val newMap = this.toLinkedMap() ++ newMap.put(pair.first, pair.second) ++ return newMap ++} ++ ++/** ++ * Create a new read-only map from a map and a list new key-value pairs ++ */ ++public fun Map.plus(pairs: Collection>): Map { ++ val newMap = this.toLinkedMap() ++ newMap.putAll(pairs) ++ return newMap ++} ++ ++/** ++ * Create a new read-only map by removing a key ++ */ ++public fun Map.minus(key: K): Map { ++ return this.filterKeys { key != it } ++} ++ ++/** ++ * Create a new read-only map by removing a list of keys","> list of + +oops +",2015-01-15 07:02:10 +572,"@@ -28,41 +28,47 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode + class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { + + val patterns = mapOf( +- ""java.io.PrintStream.println"" to ""println($0)"", +- ""java.io.PrintStream.print"" to ""print($0)"", +- ""java.util.Collections.sort"" to ""$0.sort()"" ++ ""java.io.PrintStream.println"" to Pair(""println($0)"", false),","This boolean value is quite unclear. Much better to use an enum instead. +",2016-05-23 17:59:43 +571,"@@ -28,41 +28,47 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode + class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { + + val patterns = mapOf( +- ""java.io.PrintStream.println"" to ""println($0)"", +- ""java.io.PrintStream.print"" to ""print($0)"", +- ""java.util.Collections.sort"" to ""$0.sort()"" ++ ""java.io.PrintStream.println"" to Pair(""println($0)"", false), ++ ""java.io.PrintStream.print"" to Pair(""print($0)"", false), ++ ""java.util.Collections.sort"" to Pair(""$0.sort()"", false), ++ ""java.util.HashMap.put"" to Pair(""$0[$1] = $2"", true) + ) + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { + return object : KtVisitorVoid() { + override fun visitQualifiedExpression(expression: KtQualifiedExpression) { + super.visitQualifiedExpression(expression) + +- val selectorExpression = expression.selectorExpression ?: return +- if (selectorExpression !is KtCallExpression) return +- val value = selectorExpression.valueArguments.singleOrNull() ?: return ++ val selectorExpression = expression.selectorExpression ++ if(selectorExpression !is KtCallExpression) return ++ val arguments = selectorExpression.valueArguments ++ if(arguments.isEmpty()) return + + val calleeExpression = selectorExpression.calleeExpression as KtSimpleNameExpression + val bindingContext = calleeExpression.analyze(BodyResolveMode.PARTIAL) + val target = calleeExpression.mainReference.resolveToDescriptors(bindingContext).singleOrNull() ?: return +- val pattern = target.fqNameSafe.asString() +- if (!patterns.containsKey(pattern)) return +- +- holder.registerProblem(expression, +- ""Unnecessary java usage"", +- ProblemHighlightType.WEAK_WARNING, +- UnnecessaryJavaUsageFix(patterns[pattern]!!, value.text)) ++ val pattern = patterns[target.fqNameSafe.asString()] ?: return ++ val javaUsageFix = UnnecessaryJavaUsageFix(pattern, expression.receiverExpression, arguments.map{it.text}) ++ holder.registerProblem(expression, ""Unnecessary java usage"", ProblemHighlightType.WEAK_WARNING, javaUsageFix)","Once again ""unnecessary java usage"". +",2016-05-23 17:58:23 +573,"@@ -28,41 +28,47 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode + class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { + + val patterns = mapOf( +- ""java.io.PrintStream.println"" to ""println($0)"", +- ""java.io.PrintStream.print"" to ""print($0)"", +- ""java.util.Collections.sort"" to ""$0.sort()"" ++ ""java.io.PrintStream.println"" to Pair(""println($0)"", false), ++ ""java.io.PrintStream.print"" to Pair(""print($0)"", false), ++ ""java.util.Collections.sort"" to Pair(""$0.sort()"", false), ++ ""java.util.HashMap.put"" to Pair(""$0[$1] = $2"", true) + ) + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { + return object : KtVisitorVoid() { + override fun visitQualifiedExpression(expression: KtQualifiedExpression) { + super.visitQualifiedExpression(expression) + +- val selectorExpression = expression.selectorExpression ?: return +- if (selectorExpression !is KtCallExpression) return +- val value = selectorExpression.valueArguments.singleOrNull() ?: return ++ val selectorExpression = expression.selectorExpression ++ if(selectorExpression !is KtCallExpression) return ++ val arguments = selectorExpression.valueArguments ++ if(arguments.isEmpty()) return + + val calleeExpression = selectorExpression.calleeExpression as KtSimpleNameExpression + val bindingContext = calleeExpression.analyze(BodyResolveMode.PARTIAL) + val target = calleeExpression.mainReference.resolveToDescriptors(bindingContext).singleOrNull() ?: return +- val pattern = target.fqNameSafe.asString() +- if (!patterns.containsKey(pattern)) return +- +- holder.registerProblem(expression, +- ""Unnecessary java usage"", +- ProblemHighlightType.WEAK_WARNING, +- UnnecessaryJavaUsageFix(patterns[pattern]!!, value.text)) ++ val pattern = patterns[target.fqNameSafe.asString()] ?: return ++ val javaUsageFix = UnnecessaryJavaUsageFix(pattern, expression.receiverExpression, arguments.map{it.text}) ++ holder.registerProblem(expression, ""Unnecessary java usage"", ProblemHighlightType.WEAK_WARNING, javaUsageFix) + } + } + } + +- private class UnnecessaryJavaUsageFix(val pattern: String, val value: String) : LocalQuickFix { ++ private class UnnecessaryJavaUsageFix(val pattern: Pair,","Better to unpack the pair and to use separate arguments for the text and conversion mode. +",2016-05-23 18:01:13 +969,"@@ -28,60 +28,60 @@ public inline fun TODO(reason: String): Nothing = throw NotImplementedError(""An + * Calls the specified function [block] and returns its result. + */ + @kotlin.internal.InlineOnly +-public inline fun run(block: () -> R): R = block() ++public inline fun run(@kotlin.internal.CalledInPlace(kotlin.internal.InvocationCount.EXACTLY_ONCE) block: () -> R): R = block()",Can we annotate also both `TODO` functions?,2017-08-15 15:56:21 +388,"@@ -287,16 +314,24 @@ static void replaceFile(File updatedFile, VirtualFile replacedJarFile) { + @NotNull + private static Collection getLibraryRootsWithAbiIncompatibleVersion( + @NotNull Project project, +- @NotNull ScalarIndexExtension index ++ @NotNull ScalarIndexExtension index, ++ @NotNull Predicate checkModule, ++ @NotNull Predicate checkAbiVersion + ) { + ID id = index.getName(); +- Collection abiVersions = FileBasedIndex.getInstance().getAllKeys(id, project); +- Set badAbiVersions = Sets.newHashSet(Collections2.filter(abiVersions, new Predicate() { +- @Override +- public boolean apply(Integer abiVersion) { +- return !AbiVersionUtil.isAbiVersionCompatible(abiVersion); ++ ++ Module[] modules = ModuleManager.getInstance(project).getModules(); ++ ++ List modulesToCheck = new ArrayList(); ++ for(Module module : modules) {","If you're using `Predicate`, you might as well go ahead and call `Collections2.filter` here. Also I would recommend to use `kotlin.Function1` and `KotlinPackage.filter` instead, but that's up to you +",2015-06-11 22:05:41 +387,"@@ -287,16 +314,24 @@ static void replaceFile(File updatedFile, VirtualFile replacedJarFile) { + @NotNull + private static Collection getLibraryRootsWithAbiIncompatibleVersion( + @NotNull Project project, +- @NotNull ScalarIndexExtension index ++ @NotNull ScalarIndexExtension index, ++ @NotNull Predicate checkModule, ++ @NotNull Predicate checkAbiVersion + ) { + ID id = index.getName(); +- Collection abiVersions = FileBasedIndex.getInstance().getAllKeys(id, project); +- Set badAbiVersions = Sets.newHashSet(Collections2.filter(abiVersions, new Predicate() { +- @Override +- public boolean apply(Integer abiVersion) { +- return !AbiVersionUtil.isAbiVersionCompatible(abiVersion); ++ ++ Module[] modules = ModuleManager.getInstance(project).getModules(); ++ ++ List modulesToCheck = new ArrayList(); ++ for(Module module : modules) { ++ if (checkModule.apply(module)) { ++ modulesToCheck.add(module); + } +- })); ++ } ++ if (modulesToCheck.isEmpty()) return new ArrayList();","`Collections.emptyList()`? +",2015-06-11 22:01:48 +167,"@@ -287,6 +287,10 @@ convert.negated.expression.with.demorgans.law=Convert negated expression to DeMo + convert.negated.expression.with.demorgans.law.family=Convert negated expression to DeMorgan's equivalent + split.if=Split into 2 if's + split.if.family=Split If ++make.type.explicit.in.lambda=Make types explicit ++make.type.explicit.in.lambda.family=Make Types Explicit ++make.type.implicit.in.lambda=Make types implicit ++make.type.implicit.in.lambda.family=Make Types Implicit","Why not `... in lambda` ? +",2014-04-09 15:57:50 +482,"@@ -288,8 +288,8 @@ public String render(@NotNull BadNamedArgumentsTarget target) { + + MAP.put(MANY_COMPANION_OBJECTS, ""Only one companion object is allowed per class""); + +- MAP.put(DEPRECATED_SYMBOL, ""''{0}'' is deprecated."", DEPRECATION_RENDERER); +- MAP.put(DEPRECATED_SYMBOL_WITH_MESSAGE, ""''{0}'' is deprecated. {1}"", DEPRECATION_RENDERER, STRING); ++ MAP.put(DEPRECATION, ""''{0}'' is deprecated. {1}"", DEPRECATION_RENDERER, STRING); ++ MAP.put(DEPRECATION_ERROR, ""Calling ''{0}'' is an error. {1}"", DEPRECATION_RENDERER, STRING);","I think this error message looks weird on classes in type positions... +",2015-10-10 12:09:49 +237,"@@ -288,9 +295,21 @@ public static Type getTraitImplThisParameterType(@NotNull ClassDescriptor traitD + + private static Type stringValueOfOrStringBuilderAppendType(Type type) { + int sort = type.getSort(); +- return sort == Type.OBJECT || sort == Type.ARRAY +- ? AsmTypeConstants.OBJECT_TYPE +- : sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type; ++ switch (sort) { ++ case Type.OBJECT: ++ if(STRINGBULDER_OBJECT_APPEND_ARG_TYPES.contains(type.getClassName())) {","Please add a space after `if` +",2014-05-12 20:45:52 +87,"@@ -29,27 +29,27 @@ fun main(args: Array) { + generateDomEventsAPI(File(jsCoreDir, ""domEvents.kt"")) + + iterators().writeTo(File(outDir, ""_Iterators.kt"")) { +- buildFor(Iterators, """") ++ buildFor(Iterators, null) + } + + val iterables = iterables() +- iterables.writeTo(File(outDir, ""_Arrays.kt"")) { +- buildFor(Arrays, """") ++ val sumFunctions = PrimitiveType.values().map(::sumFunction).filterNotNull() ++ (iterables+sumFunctions).writeTo(File(outDir, ""_Arrays.kt"")) { ++ buildFor(Arrays, null) + } + +- val otherArrayNames = arrayListOf(""Boolean"", ""Byte"", ""Char"", ""Short"", ""Int"", ""Long"", ""Float"", ""Double"") +- for (a in otherArrayNames) { +- iterables.writeTo(File(outDir, ""_${a}Arrays.kt"")) { +- buildFor(PrimitiveArrays, a) ++ for (primitive in PrimitiveType.values()) { ++ (iterables+sumFunction(primitive)).filterNotNull().writeTo(File(outDir, ""_${primitive.name}Arrays.kt"")) {","Let's stick to conventions: ""+"" should be surrounded by spaces +",2013-11-27 07:33:34 +231,"@@ -292,6 +292,10 @@ convert.negated.boolean.sequence=Replace negated sequence with DeMorgan equivale + convert.negated.boolean.sequence.family=Replace negated sequence with DeMorgan equivalent + convert.negated.expression.with.demorgans.law=Convert negated expression to DeMorgan's equivalent + convert.negated.expression.with.demorgans.law.family=Convert negated expression to DeMorgan's equivalent ++add.for.loop.indices=Add indices to for loop ++add.for.loop.indices.family=Add indices to for loop","Should be `Add Indices to For Loop`, take a look at https://github.com/JetBrains/kotlin/commit/5a0055cbeb90b0c6d80c223d4d68cc451d0ccfc1 +",2014-05-12 12:49:03 +232,"@@ -292,6 +292,10 @@ convert.negated.boolean.sequence=Replace negated sequence with DeMorgan equivale + convert.negated.boolean.sequence.family=Replace negated sequence with DeMorgan equivalent + convert.negated.expression.with.demorgans.law=Convert negated expression to DeMorgan's equivalent + convert.negated.expression.with.demorgans.law.family=Convert negated expression to DeMorgan's equivalent ++add.for.loop.indices=Add indices to for loop ++add.for.loop.indices.family=Add indices to for loop ++remove.for.loop.indices=Remove indices from for loop ++remove.for.loop.indices.family=Remove indices from for loop","`Remove Indices from For Loop` +",2014-05-12 12:49:12 +328,"@@ -2945,6 +2946,12 @@ public Unit invoke(InstructionAdapter v) { + }); + } + ++ private static boolean isInRangeValueType(Type type) {","There's `AsmUtil#isIntPrimitive` +",2015-03-04 20:31:13 +174,"@@ -295,7 +295,10 @@ simplify.boolean.with.constants=Simplify boolean expression + simplify.boolean.with.constants.family=Simplify boolean expression + insert.explicit.type.arguments=Add explicit type arguments + insert.explicit.type.arguments.family=Add explicit type arguments +->>>>>>> Intention for adding explicit type arguments at function calls ++make.type.explicit.in.lambda=Make types explicit ++make.type.explicit.in.lambda.family=Make Types Explicit ++make.type.implicit.in.lambda=Make types implicit ++make.type.implicit.in.lambda.family=Make Types Implicit","Why not ""Make types explicit/implicit **in lambda**""? I believe I asked you this the first time +",2014-04-16 16:44:54 +193,"@@ -295,7 +295,10 @@ simplify.boolean.with.constants=Simplify boolean expression + simplify.boolean.with.constants.family=Simplify boolean expression + insert.explicit.type.arguments=Add explicit type arguments + insert.explicit.type.arguments.family=Add explicit type arguments +->>>>>>> Intention for adding explicit type arguments at function calls ++make.type.explicit.in.lambda=Make types explicit in lambda ++make.type.explicit.in.lambda.family=Make Types Explicit In Lambda ++make.type.implicit.in.lambda=Make types implicit in lambda(may break code)","Please add a space before `(` :) +",2014-04-22 21:59:49 +194,"@@ -295,7 +295,10 @@ simplify.boolean.with.constants=Simplify boolean expression + simplify.boolean.with.constants.family=Simplify boolean expression + insert.explicit.type.arguments=Add explicit type arguments + insert.explicit.type.arguments.family=Add explicit type arguments +->>>>>>> Intention for adding explicit type arguments at function calls ++make.type.explicit.in.lambda=Make types explicit in lambda ++make.type.explicit.in.lambda.family=Make Types Explicit In Lambda ++make.type.implicit.in.lambda=Make types implicit in lambda(may break code) ++make.type.implicit.in.lambda.family=Make Types Implicit In Lambda(May Break Code)","Ditto +",2014-04-22 22:00:15 +298,"@@ -3,12 +3,12 @@ package kotlin + import java.util.* + + /** +- * Returns a new [[SortedSet]] with the initial elements ++ * Returns a new [SortedSet] with the given elements. + */ + public fun sortedSetOf(vararg values: T): TreeSet = values.toCollection(TreeSet()) + + /** +- * Returns a new [[SortedSet]] with the given *comparator* and the initial elements ++ * Returns a new [SortedSet] with the given [comparator] and initial elements.","initial -> given as in the function above +",2015-02-09 16:00:52 +950,"@@ -3,13 +3,13 @@ import kotlinApi.* + //TODO: Formatter works incorrectly + internal class A { + fun foo(c: KotlinClass): Int { +- return c.nullableProperty!!.length +- +c.property.length +- +KotlinClass.nullableStaticVar!! +- +KotlinClass.staticVar +- +KotlinClass.nullableStaticFun(1)!! +- +KotlinClass.staticFun(1) +- +nullableGlobalFunction("""")!!.length +- +globalFunction("""").length ++ return (c.nullableProperty!!.length",After changes TODO comment above your code should be removed. You've already fixed it.,2017-08-04 08:43:46 +689,"@@ -3,7 +3,7 @@ + + + +- ++ ",Why? :(,2017-04-05 11:15:01 +296,"@@ -3,7 +3,7 @@ package kotlin + import java.util.Enumeration + + /** +- * Helper to make java.util.Enumeration usable in for ++ * Helper to make [Enumeration] usable in `for` loops.","""Creates `Iterator` for an `Enumeration`"" +",2015-02-09 15:59:24 +641,"@@ -3,9 +3,9 @@ fun foo() { + fun test() {} + } + +- val d: A ++ val d = + if () { +- d = A() ++ A()","I expected to generate following code + +``` kotlin + class A { + fun test() {} + } + val d = if () { + A() + } +``` + +I don't think this new line is the problem with this pull request. + +If I have following case + +``` kotlin +fun foo() { + class A { + fun test() {} + } + + + + val d: A = A() + + d.test() + A() +} +``` + +For current kotlin plugin converts them into + +``` kotlin + class A { + fun test() { + } + } + + val d: A + + + if () { + d = A() + } +``` +",2016-10-16 07:46:40 +637,"@@ -30,5 +32,10 @@ class RemoveEmptyClassBodyInspection : IntentionBasedInspection(Rem + class RemoveEmptyClassBodyIntention : SelfTargetingOffsetIndependentIntention(KtClassBody::class.java, ""Remove empty class body"") { + override fun applyTo(element: KtClassBody, editor: Editor?) = element.delete() + +- override fun isApplicableTo(element: KtClassBody) = element.text.replace(""{"", """").replace(""}"", """").isBlank() ++ override fun isApplicableTo(element: KtClassBody): Boolean { ++ element.getStrictParentOfType()?.let {","Won't + +``` +object Foo { + class Bar {} +} +``` + +cause a false negative here? +",2016-10-13 15:07:19 +649,"@@ -31,18 +31,49 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention it.applyTo(element) ++ is KtBinaryExpression -> it.applyTo(element) ++ } ++ } ++ } ++ ++ private fun KtBinaryExpression.applyTo(element: KtCallExpression) { ++ val left = left ?: return ++ val factory = KtPsiFactory(element.project) ++ val parent = element.parent ++ when (parent) { ++ is KtQualifiedExpression -> { ++ val receiver = parent.receiverExpression ++ val newLeft = when (left) { ++ is KtDotQualifiedExpression -> left.replaceFirstReceiver(factory, receiver, parent.operationSign == KtTokens.SAFE_ACCESS) ++ else -> receiver ++ } ++ val newExpression = factory.createExpression(""${newLeft.text}${operationReference.text}${right?.text ?: """"}"")","I think `createExpressionByPattern` should be better here and below. I'm trying to avoid using `text`, when possible. +",2016-11-07 09:24:47 +693,"@@ -31,7 +31,7 @@ import java.io.InputStream + class CliVirtualFileFinder( + private val index: JvmDependenciesIndex, + private val scope: GlobalSearchScope +-) : VirtualFileFinder() { ++) : JavacVirtualFileFinder() {",Check attentively that nothing is changed without `use-javac` option,2017-04-05 11:29:09 +268,"@@ -313,14 +315,21 @@ private boolean shouldInitializeProperty(@NotNull JetProperty property) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property); + assert propertyDescriptor != null; + +- CompileTimeConstant compileTimeValue = propertyDescriptor.getCompileTimeInitializer(); ++ JetExpression initializer = property.getInitializer(); ++ ++ CompileTimeConstant initializerValue = ++ property.isVar() && initializer != null ++ ? ConstantExpressionEvaluator.OBJECT$.evaluate(initializer, state.getBindingTrace(), null)","I suggest to use a temporary trace here (and discard it) instead of `state.getBindingTrace()` so that `ConstantExpressionEvaluator` won't unexpectedly write to the global trace and alter the subsequent code generation. +",2015-01-30 13:22:36 +323,"@@ -32,15 +32,49 @@ public annotation class noinline + */ + public annotation class inline(public val strategy: InlineStrategy = InlineStrategy.AS_FUNCTION) + ++/** ++ * Specifies the strategy for JVM bytecode generation for an inline function.","It's not JVM specific. +",2015-03-02 12:11:37 +925,"@@ -32,6 +50,7 @@ interface DependenciesResolver : @Suppress(""DEPRECATION"") ScriptDependenciesReso + + sealed class ResolveResult {","I'd simplify this by assuming that the result is ""success"" iff there are no errors: +``` +data class ResolutionResult( + val dependencies: ScriptDependencies, // ScriptDependencies.Empty in case of failure + val diagnostics: List +) { + val isSuccess: Boolean get() = diagnostics.none { it.severity == ERROR } // maybe an extension +} +``` +",2017-07-25 11:29:13 +924,"@@ -32,6 +50,7 @@ interface DependenciesResolver : @Suppress(""DEPRECATION"") ScriptDependenciesReso + + sealed class ResolveResult { + abstract val dependencies: ScriptDependencies? ++ // reports -> diagnostics",+1 for `val diagnostics: List`,2017-07-25 11:25:01 +376,"@@ -327,12 +327,12 @@ else if (containingDescriptor instanceof FunctionDescriptor || containingDescrip + return defaultVisibility; + } + +- public static Modality getDefaultModality(DeclarationDescriptor containingDescriptor, boolean isBodyPresent) { ++ public static Modality getDefaultModality(DeclarationDescriptor containingDescriptor, Visibility visibility, boolean isBodyPresent) { + Modality defaultModality; + if (containingDescriptor instanceof ClassDescriptor) { + boolean isTrait = ((ClassDescriptor) containingDescriptor).getKind() == ClassKind.TRAIT; + boolean isDefinitelyAbstract = isTrait && !isBodyPresent; +- Modality basicModality = isTrait ? Modality.OPEN : Modality.FINAL; ++ Modality basicModality = isTrait && visibility != Visibilities.PRIVATE ? Modality.OPEN : Modality.FINAL;","Please use `Visibilities.isPrivate` instead & add a test on a private-to-this fun/val in a trait +",2015-04-20 14:38:27 +763,"@@ -33,10 +33,18 @@ public class StringBuilder(content: String = """") : Appendable, CharSequence { + override val length: Int + get() = string.asDynamic().length + ++ fun setLength(newLength : Int) { ++ string = string.substring(0, newLength)",This implementation doesn't conform to the `setLength` method contract.,2017-04-17 19:05:52 +766,"@@ -33,6 +33,7 @@ + public class KotlinEditorOptions implements PersistentStateComponent { + private boolean donTShowConversionDialog = false; + private boolean enableJavaToKotlinConversion = true; ++ private boolean enableSmartEditing = true;","I don't like the idea of adding a preference for this behavior. First of all, the name of the preference says nothing at all to the user. Second, if anyone becomes annoyed by the behavior, it's quite hard for them to discover how to change it.",2017-04-19 10:20:22 +576,"@@ -33,7 +33,7 @@ + + com.android.tools.build + gradle +- 1.1.0 ++ 1.3.0","I suppose this isn't strictly needed since the plugin is looked up by name. +",2016-06-06 03:48:55 +315,"@@ -34,33 +34,38 @@ private object EmptySet : Set { + override fun toString(): String = set.toString() + } + ++/** Returns an empty read-only list. */ + public fun emptyList(): List = EmptyList as List ++/** Returns an empty read-only set. */ + public fun emptySet(): Set = EmptySet as Set + + /** Returns a new read-only list of given elements */ + public fun listOf(vararg values: T): List = if (values.size() == 0) emptyList() else arrayListOf(*values) + +-/** Returns an empty read-only list */ ++/** Returns an empty read-only list. */ + public fun listOf(): List = emptyList() + +-/** Returns a new read-only ordered set of given elements */ ++/** Returns a new read-only ordered set with the given elements. */ + public fun setOf(vararg values: T): Set = if (values.size() == 0) emptySet() else values.toCollection(LinkedHashSet()) + +-/** Returns an empty read-only set */ ++/** Returns an empty read-only set. */ + public fun setOf(): Set = emptySet() + +-/** Returns a new LinkedList with a variable number of initial elements */ ++/** Returns a new LinkedList with the given elements. */","Linkify LinkedList +",2015-02-11 08:32:02 +316,"@@ -34,33 +34,38 @@ private object EmptySet : Set { + override fun toString(): String = set.toString() + } + ++/** Returns an empty read-only list. */ + public fun emptyList(): List = EmptyList as List ++/** Returns an empty read-only set. */ + public fun emptySet(): Set = EmptySet as Set + + /** Returns a new read-only list of given elements */ + public fun listOf(vararg values: T): List = if (values.size() == 0) emptyList() else arrayListOf(*values) + +-/** Returns an empty read-only list */ ++/** Returns an empty read-only list. */ + public fun listOf(): List = emptyList() + +-/** Returns a new read-only ordered set of given elements */ ++/** Returns a new read-only ordered set with the given elements. */ + public fun setOf(vararg values: T): Set = if (values.size() == 0) emptySet() else values.toCollection(LinkedHashSet()) + +-/** Returns an empty read-only set */ ++/** Returns an empty read-only set. */ + public fun setOf(): Set = emptySet() + +-/** Returns a new LinkedList with a variable number of initial elements */ ++/** Returns a new LinkedList with the given elements. */ + public fun linkedListOf(vararg values: T): LinkedList = values.toCollection(LinkedList()) + +-/** Returns a new ArrayList with a variable number of initial elements */ ++/** Returns a new ArrayList with the given elements. */ + public fun arrayListOf(vararg values: T): ArrayList = values.toCollection(ArrayList(values.size())) + +-/** Returns a new HashSet with a variable number of initial elements */ ++/** Returns a new HashSet with the given elements. */ + public fun hashSetOf(vararg values: T): HashSet = values.toCollection(HashSet(values.size())) + +-/** Returns a new LinkedHashSet with a variable number of initial elements */ ++/** Returns a new LinkedHashSet with the given elements. */ + public fun linkedSetOf(vararg values: T): LinkedHashSet = values.toCollection(LinkedHashSet(values.size())) + ++/** ++ * Returns the valid indices for this collection.","Returns an IntRange specifying the valid... +",2015-02-11 08:32:43 +537,"@@ -35,15 +34,45 @@ class ConvertToForEachFunctionCallIntention : SelfTargetingIntention$2}"", element.loopRange!!, loopParameter, functionBodyArgument) +- val result = element.replace(foreachExpression) ++ val result = element.replace(foreachExpression) as KtElement ++ ++ result.getContinuesWithLabel(labelName).forEach { ++ it.replace(psiFactory.createExpression(""return@forEach"")) ++ } + + commentSaver.restore(result) + } ++ ++ private fun KtElement.getContinuesWithLabel(labelName: String?): List { ++ val continueElements = ArrayList() ++ ++ forEachDescendantOfType({ it !is KtLoopExpression }) {","I think the code will be cleaner if you merge the two loops into one. +",2016-04-05 12:30:16 +23,"@@ -35,33 +34,35 @@ + + import javax.swing.*; + +-public class DescriptorClassMember implements ClassMemberWithElement { ++public class DescriptorClassMember extends MemberChooserObjectBase implements ClassMemberWithElement {","Copying replaced with delegation, please, pay attention - I rebased on master and squash fix into existing commit. +",2013-01-15 19:29:16 +437,"@@ -35,6 +35,16 @@ target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.FI + public annotation(retention = AnnotationRetention.RUNTIME, mustBeDocumented = true) class jvmStatic + + /** ++ * Specifies the name for the target platform element (Java method, JavaScript function)","Documentation should probably not mention JavaScript anymore +",2015-08-25 12:48:50 +948,"@@ -354,11 +360,11 @@ fun KtTypeParameterListOwner.addTypeParameter(typeParameter: KtTypeParameter): K + val list = KtPsiFactory(this).createTypeParameterList("""") + list.parameters[0].replace(typeParameter) + val leftAnchor = when (this) { +- is KtClass -> nameIdentifier ?: getClassOrInterfaceKeyword() +- is KtNamedFunction -> funKeyword +- is KtProperty -> valOrVarKeyword +- else -> null +- } ?: return null ++ is KtClass -> nameIdentifier ?: getClassOrInterfaceKeyword()","There is a lot of unnecessary code formatting, which make harder to find what exactly author of PR changed. @Dimach, did was intentional and done by you or automatically changed by IntelliJ?",2017-08-03 12:50:40 +570,"@@ -36,15 +40,18 @@ class UnnecessaryJavaUsageInspection : AbstractKotlinInspection(), CleanupLocalI + + val selectorExpression = expression.selectorExpression ?: return + if (selectorExpression !is KtCallExpression) return +- if (selectorExpression.valueArguments.size != 1) return +- val value = selectorExpression.valueArguments[0].text +- val pattern = expression.text.replace(value, ""$0"") ++ val value = selectorExpression.valueArguments.singleOrNull() ?: return ++ ++ val calleeExpression = selectorExpression.calleeExpression as KtSimpleNameExpression","The calleeExpression is not always a KtSimpleNameExpression, so you should use a safe cast here. +",2016-05-23 17:57:41 +991,"@@ -367,7 +368,8 @@ class ControlFlowInformationProvider private constructor( + // Do not consider top-level properties + if (containingDeclarationDescriptor is PackageFragmentDescriptor) return false + var parentDeclaration = getElementParentDeclaration(writeValueInstruction.element) +- while (true) { ++ ++ loop@ while (true) {",I recommend some self-describing name for this label,2017-08-16 09:39:02 +516,"@@ -37,18 +37,19 @@ class AnnotatedClassDescriptor(classFqName: String) : AnnotatedElementDescriptor + } + + class AnnotatedMethodDescriptor(classFqName: String, public val methodName: String) : AnnotatedElementDescriptor(classFqName) { +- override fun equals(other: Any?) = other is AnnotatedMethodDescriptor && methodName == other.methodName ++ override fun equals(other: Any?) = other is AnnotatedMethodDescriptor && methodName == other.methodName && classFqName == other.classFqName + +- override fun hashCode() = methodName.hashCode() ++ override fun hashCode() = methodName.hashCode() + classFqName.hashCode()","Is it the best way to combine hashcodes? +",2016-02-18 01:36:46 +545,"@@ -371,6 +371,8 @@ class QuickFixRegistrar : QuickFixContributor { + + DATA_CLASS_NOT_PROPERTY_PARAMETER.registerFactory(AddValVarToConstructorParameterAction.QuickFixFactory) + +- NON_LOCAL_RETURN_NOT_ALLOWED.registerFactory(AddCrossInlineFix) ++ NON_LOCAL_RETURN_NOT_ALLOWED.registerFactory(ConvertExtensionToFunctionTypeFix)","This seems to be an accidental change, please revert +",2016-04-28 08:30:42 +149,"@@ -3731,6 +3738,160 @@ else if (condition instanceof JetWhenConditionWithExpression) { + } + } + ++ private StackValue generateSwitch(JetWhenExpression expression, Type subjectType, Type resultType, boolean isStatement) { ++ JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); ++ assert subjectJetType != null; ++ ++ Map transitions = Maps.newTreeMap(); ++ ++ Label[] entryLabels = new Label[expression.getEntries().size()]; ++ int entryLabelsCounter = 0; ++ ++ Label elseLabel = new Label(); ++ Label endLabel = new Label(); ++ boolean hasElse = expression.getElseExpression() != null; ++ ++ for (JetWhenEntry entry : expression.getEntries()) { ++ Label entryLabel = new Label(); ++ ++ for (JetWhenCondition condition : entry.getConditions()) { ++ assert condition instanceof JetWhenConditionWithExpression; ++ ++ JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression(); ++ assert conditionExpression != null; ++ ++ CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext); ++ assert doesConstantFitForSwitch(constant); ++ ++ int value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).intValue() : ((Character)constant.getValue()).charValue(); ++ ++ if (!transitions.containsKey(value)) { ++ transitions.put(value, entryLabel); ++ } ++ } ++ ++ if (entry.isElse()) { ++ elseLabel = entryLabel; ++ } ++ ++ entryLabels[entryLabelsCounter++] = entryLabel; ++ } ++ ++ gen(expression.getSubjectExpression(), subjectType); ++ generateSwitchCall( ++ transitions, ++ //if there is no else-entry and it's statement then default --- endLabel ++ (hasElse || !isStatement) ? elseLabel : endLabel ++ ); ++ ++ //resolving entries' labels ++ int i = 0; ++ for (JetWhenEntry entry : expression.getEntries()) { ++ v.visitLabel(entryLabels[i++]); ++ ++ FrameMap.Mark mark = myFrameMap.mark(); ++ gen(entry.getExpression(), resultType); ++ mark.dropTo(); ++ ++ if (!entry.isElse()) { ++ v.goTo(endLabel); ++ } ++ } ++ ++ //there is no else-entry but this is not statement, so we should return Unit ++ if (!hasElse && !isStatement) { ++ v.visitLabel(elseLabel); ++ // a result is expected ++ if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { ++ // when() is supposed to be exhaustive ++ throwNewException(""kotlin/NoWhenBranchMatchedException""); ++ } ++ else { ++ // non-exhaustive when() with no else -> Unit must be expected ++ StackValue.putUnitInstance(v); ++ } ++ }","Please, get rid of code duplication. +",2014-04-08 16:03:12 +150,"@@ -3731,6 +3738,160 @@ else if (condition instanceof JetWhenConditionWithExpression) { + } + } + ++ private StackValue generateSwitch(JetWhenExpression expression, Type subjectType, Type resultType, boolean isStatement) { ++ JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); ++ assert subjectJetType != null; ++ ++ Map transitions = Maps.newTreeMap(); ++ ++ Label[] entryLabels = new Label[expression.getEntries().size()]; ++ int entryLabelsCounter = 0; ++ ++ Label elseLabel = new Label(); ++ Label endLabel = new Label(); ++ boolean hasElse = expression.getElseExpression() != null; ++ ++ for (JetWhenEntry entry : expression.getEntries()) { ++ Label entryLabel = new Label(); ++ ++ for (JetWhenCondition condition : entry.getConditions()) { ++ assert condition instanceof JetWhenConditionWithExpression; ++ ++ JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression(); ++ assert conditionExpression != null; ++ ++ CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext); ++ assert doesConstantFitForSwitch(constant); ++ ++ int value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).intValue() : ((Character)constant.getValue()).charValue(); ++ ++ if (!transitions.containsKey(value)) { ++ transitions.put(value, entryLabel); ++ } ++ } ++ ++ if (entry.isElse()) { ++ elseLabel = entryLabel; ++ } ++ ++ entryLabels[entryLabelsCounter++] = entryLabel; ++ } ++ ++ gen(expression.getSubjectExpression(), subjectType); ++ generateSwitchCall( ++ transitions, ++ //if there is no else-entry and it's statement then default --- endLabel ++ (hasElse || !isStatement) ? elseLabel : endLabel ++ ); ++ ++ //resolving entries' labels ++ int i = 0; ++ for (JetWhenEntry entry : expression.getEntries()) { ++ v.visitLabel(entryLabels[i++]); ++ ++ FrameMap.Mark mark = myFrameMap.mark(); ++ gen(entry.getExpression(), resultType); ++ mark.dropTo(); ++ ++ if (!entry.isElse()) { ++ v.goTo(endLabel); ++ } ++ } ++ ++ //there is no else-entry but this is not statement, so we should return Unit ++ if (!hasElse && !isStatement) { ++ v.visitLabel(elseLabel); ++ // a result is expected ++ if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { ++ // when() is supposed to be exhaustive ++ throwNewException(""kotlin/NoWhenBranchMatchedException""); ++ } ++ else { ++ // non-exhaustive when() with no else -> Unit must be expected ++ StackValue.putUnitInstance(v); ++ } ++ } ++ ++ markLineNumber(expression); ++ v.mark(endLabel); ++ ++ return StackValue.onStack(resultType); ++ } ++ ++ private void generateSwitchCall(Map transitions, Label defaultLabel) {","What does ""call"" mean here? +",2014-04-08 16:04:14 +151,"@@ -3731,6 +3738,160 @@ else if (condition instanceof JetWhenConditionWithExpression) { + } + } + ++ private StackValue generateSwitch(JetWhenExpression expression, Type subjectType, Type resultType, boolean isStatement) { ++ JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); ++ assert subjectJetType != null; ++ ++ Map transitions = Maps.newTreeMap(); ++ ++ Label[] entryLabels = new Label[expression.getEntries().size()]; ++ int entryLabelsCounter = 0; ++ ++ Label elseLabel = new Label(); ++ Label endLabel = new Label(); ++ boolean hasElse = expression.getElseExpression() != null; ++ ++ for (JetWhenEntry entry : expression.getEntries()) { ++ Label entryLabel = new Label(); ++ ++ for (JetWhenCondition condition : entry.getConditions()) { ++ assert condition instanceof JetWhenConditionWithExpression; ++ ++ JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression(); ++ assert conditionExpression != null; ++ ++ CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext); ++ assert doesConstantFitForSwitch(constant); ++ ++ int value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).intValue() : ((Character)constant.getValue()).charValue(); ++ ++ if (!transitions.containsKey(value)) { ++ transitions.put(value, entryLabel); ++ } ++ } ++ ++ if (entry.isElse()) { ++ elseLabel = entryLabel; ++ } ++ ++ entryLabels[entryLabelsCounter++] = entryLabel; ++ } ++ ++ gen(expression.getSubjectExpression(), subjectType); ++ generateSwitchCall( ++ transitions, ++ //if there is no else-entry and it's statement then default --- endLabel ++ (hasElse || !isStatement) ? elseLabel : endLabel ++ ); ++ ++ //resolving entries' labels ++ int i = 0; ++ for (JetWhenEntry entry : expression.getEntries()) { ++ v.visitLabel(entryLabels[i++]); ++ ++ FrameMap.Mark mark = myFrameMap.mark(); ++ gen(entry.getExpression(), resultType); ++ mark.dropTo(); ++ ++ if (!entry.isElse()) { ++ v.goTo(endLabel); ++ } ++ } ++ ++ //there is no else-entry but this is not statement, so we should return Unit ++ if (!hasElse && !isStatement) { ++ v.visitLabel(elseLabel); ++ // a result is expected ++ if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { ++ // when() is supposed to be exhaustive ++ throwNewException(""kotlin/NoWhenBranchMatchedException""); ++ } ++ else { ++ // non-exhaustive when() with no else -> Unit must be expected ++ StackValue.putUnitInstance(v); ++ } ++ } ++ ++ markLineNumber(expression); ++ v.mark(endLabel); ++ ++ return StackValue.onStack(resultType); ++ } ++ ++ private void generateSwitchCall(Map transitions, Label defaultLabel) { ++ int[] keys = new int[transitions.size()]; ++ Label[] labels = new Label[transitions.size()]; ++ int i = 0; ++ ++ for (Map.Entry transition : transitions.entrySet()) { ++ keys[i] = transition.getKey(); ++ labels[i] = transition.getValue(); ++ ++ i++; ++ } ++ ++ int hi = keys[keys.length-1]; ++ int lo = keys[0]; ++ long emptyCells = ((long)hi - (long)lo + 1) - keys.length; ++ ++ boolean useTableSwitch = keys.length > 0 && ++ 10L * emptyCells <= (long) keys.length; // less then 10% of empty cells ++ ++ if (!useTableSwitch) { ++ v.lookupswitch(defaultLabel, keys, labels); ++ return; ++ } ++ ++ Label[] sparseLabels = new Label[hi-lo + 1]; ++ Arrays.fill(sparseLabels, defaultLabel); ++ ++ for (i = 0; i < keys.length; i++) { ++ sparseLabels[keys[i] - lo] = labels[i]; ++ } ++ ++ v.tableswitch(lo, hi, defaultLabel, sparseLabels); ++ } ++ ++ private boolean doesConstantFitForSwitch(CompileTimeConstant constant) {","IDEA says this method can be static. And I believe it ;) +",2014-04-08 16:04:30 +152,"@@ -3731,6 +3738,160 @@ else if (condition instanceof JetWhenConditionWithExpression) { + } + } + ++ private StackValue generateSwitch(JetWhenExpression expression, Type subjectType, Type resultType, boolean isStatement) { ++ JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); ++ assert subjectJetType != null; ++ ++ Map transitions = Maps.newTreeMap(); ++ ++ Label[] entryLabels = new Label[expression.getEntries().size()]; ++ int entryLabelsCounter = 0; ++ ++ Label elseLabel = new Label(); ++ Label endLabel = new Label(); ++ boolean hasElse = expression.getElseExpression() != null; ++ ++ for (JetWhenEntry entry : expression.getEntries()) { ++ Label entryLabel = new Label(); ++ ++ for (JetWhenCondition condition : entry.getConditions()) { ++ assert condition instanceof JetWhenConditionWithExpression; ++ ++ JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression(); ++ assert conditionExpression != null; ++ ++ CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext); ++ assert doesConstantFitForSwitch(constant); ++ ++ int value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).intValue() : ((Character)constant.getValue()).charValue(); ++ ++ if (!transitions.containsKey(value)) { ++ transitions.put(value, entryLabel); ++ } ++ } ++ ++ if (entry.isElse()) { ++ elseLabel = entryLabel; ++ } ++ ++ entryLabels[entryLabelsCounter++] = entryLabel; ++ } ++ ++ gen(expression.getSubjectExpression(), subjectType); ++ generateSwitchCall( ++ transitions, ++ //if there is no else-entry and it's statement then default --- endLabel ++ (hasElse || !isStatement) ? elseLabel : endLabel ++ ); ++ ++ //resolving entries' labels ++ int i = 0; ++ for (JetWhenEntry entry : expression.getEntries()) { ++ v.visitLabel(entryLabels[i++]); ++ ++ FrameMap.Mark mark = myFrameMap.mark(); ++ gen(entry.getExpression(), resultType); ++ mark.dropTo(); ++ ++ if (!entry.isElse()) { ++ v.goTo(endLabel); ++ } ++ } ++ ++ //there is no else-entry but this is not statement, so we should return Unit ++ if (!hasElse && !isStatement) { ++ v.visitLabel(elseLabel); ++ // a result is expected ++ if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { ++ // when() is supposed to be exhaustive ++ throwNewException(""kotlin/NoWhenBranchMatchedException""); ++ } ++ else { ++ // non-exhaustive when() with no else -> Unit must be expected ++ StackValue.putUnitInstance(v); ++ } ++ } ++ ++ markLineNumber(expression); ++ v.mark(endLabel); ++ ++ return StackValue.onStack(resultType); ++ } ++ ++ private void generateSwitchCall(Map transitions, Label defaultLabel) { ++ int[] keys = new int[transitions.size()]; ++ Label[] labels = new Label[transitions.size()]; ++ int i = 0; ++ ++ for (Map.Entry transition : transitions.entrySet()) { ++ keys[i] = transition.getKey(); ++ labels[i] = transition.getValue(); ++ ++ i++; ++ } ++ ++ int hi = keys[keys.length-1]; ++ int lo = keys[0]; ++ long emptyCells = ((long)hi - (long)lo + 1) - keys.length; ++ ++ boolean useTableSwitch = keys.length > 0 && ++ 10L * emptyCells <= (long) keys.length; // less then 10% of empty cells ++ ++ if (!useTableSwitch) { ++ v.lookupswitch(defaultLabel, keys, labels); ++ return; ++ } ++ ++ Label[] sparseLabels = new Label[hi-lo + 1]; ++ Arrays.fill(sparseLabels, defaultLabel); ++ ++ for (i = 0; i < keys.length; i++) { ++ sparseLabels[keys[i] - lo] = labels[i]; ++ } ++ ++ v.tableswitch(lo, hi, defaultLabel, sparseLabels); ++ } ++ ++ private boolean doesConstantFitForSwitch(CompileTimeConstant constant) { ++ if (constant == null || !(constant instanceof IntegerValueConstant)) {","`constant == null` can be removed, because ""instanceof"" is false for null anyway +",2014-04-08 16:04:38 +153,"@@ -3731,6 +3738,160 @@ else if (condition instanceof JetWhenConditionWithExpression) { + } + } + ++ private StackValue generateSwitch(JetWhenExpression expression, Type subjectType, Type resultType, boolean isStatement) { ++ JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); ++ assert subjectJetType != null; ++ ++ Map transitions = Maps.newTreeMap(); ++ ++ Label[] entryLabels = new Label[expression.getEntries().size()]; ++ int entryLabelsCounter = 0; ++ ++ Label elseLabel = new Label(); ++ Label endLabel = new Label(); ++ boolean hasElse = expression.getElseExpression() != null; ++ ++ for (JetWhenEntry entry : expression.getEntries()) { ++ Label entryLabel = new Label(); ++ ++ for (JetWhenCondition condition : entry.getConditions()) { ++ assert condition instanceof JetWhenConditionWithExpression; ++ ++ JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression(); ++ assert conditionExpression != null; ++ ++ CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext); ++ assert doesConstantFitForSwitch(constant); ++ ++ int value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).intValue() : ((Character)constant.getValue()).charValue(); ++ ++ if (!transitions.containsKey(value)) { ++ transitions.put(value, entryLabel); ++ } ++ } ++ ++ if (entry.isElse()) { ++ elseLabel = entryLabel; ++ } ++ ++ entryLabels[entryLabelsCounter++] = entryLabel; ++ } ++ ++ gen(expression.getSubjectExpression(), subjectType); ++ generateSwitchCall( ++ transitions, ++ //if there is no else-entry and it's statement then default --- endLabel ++ (hasElse || !isStatement) ? elseLabel : endLabel ++ ); ++ ++ //resolving entries' labels ++ int i = 0; ++ for (JetWhenEntry entry : expression.getEntries()) { ++ v.visitLabel(entryLabels[i++]); ++ ++ FrameMap.Mark mark = myFrameMap.mark(); ++ gen(entry.getExpression(), resultType); ++ mark.dropTo(); ++ ++ if (!entry.isElse()) { ++ v.goTo(endLabel); ++ } ++ } ++ ++ //there is no else-entry but this is not statement, so we should return Unit ++ if (!hasElse && !isStatement) { ++ v.visitLabel(elseLabel); ++ // a result is expected ++ if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { ++ // when() is supposed to be exhaustive ++ throwNewException(""kotlin/NoWhenBranchMatchedException""); ++ } ++ else { ++ // non-exhaustive when() with no else -> Unit must be expected ++ StackValue.putUnitInstance(v); ++ } ++ } ++ ++ markLineNumber(expression); ++ v.mark(endLabel); ++ ++ return StackValue.onStack(resultType); ++ } ++ ++ private void generateSwitchCall(Map transitions, Label defaultLabel) { ++ int[] keys = new int[transitions.size()]; ++ Label[] labels = new Label[transitions.size()]; ++ int i = 0; ++ ++ for (Map.Entry transition : transitions.entrySet()) { ++ keys[i] = transition.getKey(); ++ labels[i] = transition.getValue(); ++ ++ i++; ++ } ++ ++ int hi = keys[keys.length-1]; ++ int lo = keys[0]; ++ long emptyCells = ((long)hi - (long)lo + 1) - keys.length; ++ ++ boolean useTableSwitch = keys.length > 0 && ++ 10L * emptyCells <= (long) keys.length; // less then 10% of empty cells ++ ++ if (!useTableSwitch) { ++ v.lookupswitch(defaultLabel, keys, labels); ++ return; ++ } ++ ++ Label[] sparseLabels = new Label[hi-lo + 1]; ++ Arrays.fill(sparseLabels, defaultLabel); ++ ++ for (i = 0; i < keys.length; i++) { ++ sparseLabels[keys[i] - lo] = labels[i]; ++ } ++ ++ v.tableswitch(lo, hi, defaultLabel, sparseLabels); ++ } ++ ++ private boolean doesConstantFitForSwitch(CompileTimeConstant constant) { ++ if (constant == null || !(constant instanceof IntegerValueConstant)) { ++ return false; ++ } ++ ++ long value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).longValue() : ((Character)constant.getValue()).charValue(); ++ return value >= Integer.MIN_VALUE && ++ value <= Integer.MAX_VALUE;","This check seems redundant, because we already checked that constant is not `long` +",2014-04-08 16:04:46 +154,"@@ -3731,6 +3738,160 @@ else if (condition instanceof JetWhenConditionWithExpression) { + } + } + ++ private StackValue generateSwitch(JetWhenExpression expression, Type subjectType, Type resultType, boolean isStatement) { ++ JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); ++ assert subjectJetType != null; ++ ++ Map transitions = Maps.newTreeMap(); ++ ++ Label[] entryLabels = new Label[expression.getEntries().size()]; ++ int entryLabelsCounter = 0; ++ ++ Label elseLabel = new Label(); ++ Label endLabel = new Label(); ++ boolean hasElse = expression.getElseExpression() != null; ++ ++ for (JetWhenEntry entry : expression.getEntries()) { ++ Label entryLabel = new Label(); ++ ++ for (JetWhenCondition condition : entry.getConditions()) { ++ assert condition instanceof JetWhenConditionWithExpression; ++ ++ JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression(); ++ assert conditionExpression != null; ++ ++ CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext); ++ assert doesConstantFitForSwitch(constant); ++ ++ int value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).intValue() : ((Character)constant.getValue()).charValue(); ++ ++ if (!transitions.containsKey(value)) { ++ transitions.put(value, entryLabel); ++ } ++ } ++ ++ if (entry.isElse()) { ++ elseLabel = entryLabel; ++ } ++ ++ entryLabels[entryLabelsCounter++] = entryLabel; ++ } ++ ++ gen(expression.getSubjectExpression(), subjectType); ++ generateSwitchCall( ++ transitions, ++ //if there is no else-entry and it's statement then default --- endLabel ++ (hasElse || !isStatement) ? elseLabel : endLabel ++ ); ++ ++ //resolving entries' labels ++ int i = 0; ++ for (JetWhenEntry entry : expression.getEntries()) { ++ v.visitLabel(entryLabels[i++]); ++ ++ FrameMap.Mark mark = myFrameMap.mark(); ++ gen(entry.getExpression(), resultType); ++ mark.dropTo(); ++ ++ if (!entry.isElse()) { ++ v.goTo(endLabel); ++ } ++ } ++ ++ //there is no else-entry but this is not statement, so we should return Unit ++ if (!hasElse && !isStatement) { ++ v.visitLabel(elseLabel); ++ // a result is expected ++ if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { ++ // when() is supposed to be exhaustive ++ throwNewException(""kotlin/NoWhenBranchMatchedException""); ++ } ++ else { ++ // non-exhaustive when() with no else -> Unit must be expected ++ StackValue.putUnitInstance(v); ++ } ++ } ++ ++ markLineNumber(expression); ++ v.mark(endLabel); ++ ++ return StackValue.onStack(resultType); ++ } ++ ++ private void generateSwitchCall(Map transitions, Label defaultLabel) { ++ int[] keys = new int[transitions.size()]; ++ Label[] labels = new Label[transitions.size()]; ++ int i = 0; ++ ++ for (Map.Entry transition : transitions.entrySet()) { ++ keys[i] = transition.getKey(); ++ labels[i] = transition.getValue(); ++ ++ i++; ++ } ++ ++ int hi = keys[keys.length-1]; ++ int lo = keys[0]; ++ long emptyCells = ((long)hi - (long)lo + 1) - keys.length; ++ ++ boolean useTableSwitch = keys.length > 0 && ++ 10L * emptyCells <= (long) keys.length; // less then 10% of empty cells ++ ++ if (!useTableSwitch) { ++ v.lookupswitch(defaultLabel, keys, labels); ++ return; ++ } ++ ++ Label[] sparseLabels = new Label[hi-lo + 1]; ++ Arrays.fill(sparseLabels, defaultLabel); ++ ++ for (i = 0; i < keys.length; i++) { ++ sparseLabels[keys[i] - lo] = labels[i]; ++ } ++ ++ v.tableswitch(lo, hi, defaultLabel, sparseLabels); ++ } ++ ++ private boolean doesConstantFitForSwitch(CompileTimeConstant constant) { ++ if (constant == null || !(constant instanceof IntegerValueConstant)) { ++ return false; ++ } ++ ++ long value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).longValue() : ((Character)constant.getValue()).charValue(); ++ return value >= Integer.MIN_VALUE && ++ value <= Integer.MAX_VALUE; ++ } ++ ++ private boolean canSwitchBeUsedIn(JetWhenExpression expression, Type subjectType) { ++ int typeSort = subjectType.getSort(); ++ ++ if (typeSort != Type.INT && typeSort != Type.CHAR && typeSort != Type.SHORT && typeSort != Type.BYTE) { ++ return false; ++ } ++ ++ for (JetWhenEntry entry : expression.getEntries()) { ++ for (JetWhenCondition condition : entry.getConditions()) { ++ if (!(condition instanceof JetWhenConditionWithExpression)) { ++ return false; ++ } ++ ++ //ensure that expression is constant ++ JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); ++ ++ if (patternExpression == null) {","Should be replaced with assert, because it can be null only for code with syntax errors. + +Common rule: if some method of PSI (`JetExpression`, `JetWhenCondition`, `JetWhatever`...) is annotated as `@Nullable @IfNotParsed`, it returns null only if code has syntax errors. Front-end should be tolerant to nulls here, while back-end can be assert it. +",2014-04-08 16:07:20 +841,"@@ -375,6 +382,7 @@ + + + ++ ",This string must be removed due to licensing problems,2017-05-03 13:13:59 +907,"@@ -38,17 +37,27 @@ class SwitchConverter(private val codeConverter: CodeConverter) { + + val result = ArrayList() + var pendingSelectors = ArrayList() ++ var defaultSelector: WhenEntrySelector? = null ++ var defaultEntry: WhenEntry? = null + for ((i, case) in cases.withIndex()) { + if (case.label == null) { // invalid switch - no case labels + result.add(WhenEntry(listOf(ValueWhenEntrySelector(Expression.Empty).assignNoPrototype()), convertCaseStatementsToBody(cases, i)).assignNoPrototype()) + continue + } +- pendingSelectors.add(codeConverter.convertStatement(case.label) as WhenEntrySelector) ++ (codeConverter.convertStatement(case.label) as WhenEntrySelector).run {","I'd extracted selector to a variable, then smart-cast on line 54 will calculate properly.",2017-07-17 19:23:05 +327,"@@ -3833,6 +3833,9 @@ public Unit invoke(InstructionAdapter v) { + v.mark(nonnull); + } + } ++ else if (value.type == Type.VOID_TYPE) { ++ v.aconst(null); ++ } + else { + v.dup(); + generateInstanceOfInstruction(rightType);","Similar code is present in `generateInstanceOf` which probably means `Unit is Int?` is also affected? +",2015-03-04 20:27:42 +349,"@@ -386,6 +386,10 @@ else if (containingDeclaration instanceof PackageFragmentDescriptor) { + @Override + public void visitCallExpression(@NotNull JetCallExpression expression) { + super.visitCallExpression(expression); ++ checkSamCall(expression); ++ } ++ ++ public void checkSamCall(@NotNull JetCallElement expression) {","public? +",2015-03-26 17:11:14 +471,"@@ -39,54 +39,111 @@ import kotlin.concurrent.read + import kotlin.concurrent.write + + ++fun nowSeconds() = System.nanoTime() / 1000000000L ++ + class CompileServiceImpl>( + val registry: Registry,","How long this thing work? Does it shutdown itself? +",2015-09-08 18:34:25 +606,"@@ -39,7 +39,10 @@ class SwitchConverter(private val codeConverter: CodeConverter) { + continue + } + pendingSelectors.add(codeConverter.convertStatement(case.label) as WhenEntrySelector) +- if (case.statements.isNotEmpty()) { ++ if (!case.label.isDefaultCase && case.statements.isEmpty() && cases[i + 1]?.label!!.isDefaultCase){","You are accessing `cases[i+1]` without checking that `i+1` is a valid index in the `cases` collection. +",2016-09-12 18:39:58 +895,"@@ -39,7 +39,9 @@ class ClassBody ( + builder append "" "" append lBrace append ""\n"" + + if (!classKind.isEnum()) { +- builder.append(membersFiltered, ""\n"") ++ builder.append(membersFiltered.sortedWith(Comparator { o1, o2 ->",Please extract variable to deduplicate this code,2017-07-14 00:12:32 +314,"@@ -39,7 +41,7 @@ class GenericFunction(val signature: String) : Comparable { + var receiverAsterisk = false + val inlineFamilies = HashMap() + +- val buildFamilies = HashSet(defaultFamilies.toList()) ++ val buildFamilies = HashSet(defaultFamilies.filter { it != RangesOfPrimitives && it != ProgressionsOfPrimitives }.toList())","Why is this filtering here? It seem to have no effect, anyway. +",2015-02-10 20:05:32 +837,"@@ -394,6 +394,8 @@ public static DiagnosticRenderer getRendererForDiagnostic(@NotNull Diagnostic di + MAP.put(IS_ENUM_ENTRY, ""'is' over enum entry is not allowed, use comparison instead""); + MAP.put(ENUM_ENTRY_AS_TYPE, ""Use of enum entry names as types is not allowed, use enum type instead""); + MAP.put(USELESS_NULLABLE_CHECK, ""Non-null type is checked for instance of nullable type""); ++ MAP.put(USELESS_IS_CHECK, ""'is' check is always true""); ++ MAP.put(USELESS_IS_NOT_CHECK, ""'!is' check is always false"");","Then here: +``` +MAP.put(USELESS_IS_CHECK, ""Check for instance is always ''{0}''"", TO_STRING); +```",2017-05-02 18:34:47 +512,"@@ -3975,4 +3981,19 @@ private NonLocalReturnInfo(Type type, String name) { + labelName = name; + } + } ++ ++ private StackValue getCompileTimeConstant(@NotNull KtExpression expression) {","Combine this method with original one by adding checkPure flag, and create overload with original signature to keep old invocations +",2016-02-10 09:48:42 +967,"@@ -398,4 +401,13 @@ class CallCompleter( + val expressionType = trace.getType(expression.receiverExpression) + return expressionType != null && TypeUtils.isNullableType(expressionType) + } ++ ++ private fun MutableResolvedCall<*>.updateResultDataFlowInfoUsingEffects(bindingTrace: BindingTrace) { ++ val moduleDescriptor = DescriptorUtils.getContainingModule(this.resultingDescriptor?.containingDeclaration ?: return) ++ ++ val resultDFIfromES = effectSystem.getResultDataFlowInfo(this, bindingTrace, moduleDescriptor) ++ this.dataFlowInfoForArguments.updateResultInfo(resultDFIfromES) ++ ++ effectSystem.recordDefiniteInvocations(this, bindingTrace, moduleDescriptor)","This line appears in the last but one commit, when the language features were added. It's quite unclear for me, why it appears in this commit.",2017-08-15 15:49:08 +914,"@@ -4,5 +4,110 @@ package kotlin.js + * Exposes the [Date API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) to Kotlin. + */ + public external class Date() { +- public fun getTime(): Double ++ ++ constructor(timestamp: Long) ++ constructor(dateString: String) ++ constructor(year: Int, ++ month: Int = definedExternally, ++ date: Int = definedExternally, ++ hours: Int = definedExternally, ++ minutes: Int = definedExternally, ++ seconds: Int = definedExternally, ++ millis: Int = definedExternally) ++ ++ public fun getDate(): Int = definedExternally ++ public fun getDay(): Int = definedExternally ++ public fun getFullYear(): Int = definedExternally ++ public fun getHours(): Int = definedExternally ++ public fun getMilliseconds(): Int = definedExternally ++ public fun getMinutes(): Int = definedExternally ++ public fun getMonth(): Int = definedExternally ++ public fun getSeconds(): Int = definedExternally ++ public fun getTime(): Long = definedExternally ++ ++ public fun getTimezoneOffset(): Int = definedExternally ++ public fun getUTCDate(): Int = definedExternally ++ public fun getUTCDay(): Int = definedExternally ++ public fun getUTCFullYear(): Int = definedExternally ++ public fun getUTCHours(): Int = definedExternally ++ public fun getUTCMilliseconds(): Int = definedExternally ++ public fun getUTCMinutes(): Int = definedExternally ++ public fun getUTCMonth(): Int = definedExternally ++ public fun getUTCSeconds(): Int = definedExternally ++ ++ @Deprecated(""Returns the year (usually 2-3 digits) in the specified date according to local time."", ++ ReplaceWith(""getFullYear"")) ++ public fun getYear(): Int = definedExternally ++ ++ ++ ++ public fun setDate(date: Int): Long = definedExternally ++ public fun setFullYear(year: Int, ++ month: Int = definedExternally, ++ day: Int = definedExternally): Long = definedExternally ++ public fun setHours(hours: Int, ++ minutes: Int = definedExternally, ++ seconds: Int = definedExternally, ++ millis: Int = definedExternally): Long = definedExternally ++ public fun setMilliseconds(millis: Int): Long = definedExternally ++ public fun setMinutes(minutes: Int, ++ seconds: Int = definedExternally, ++ millis: Int = definedExternally): Long = definedExternally ++ public fun setMonth(month: Int, ++ day: Int = definedExternally) ++ public fun setSeconds(seconds: Int, ++ millis: Int = definedExternally): Long = definedExternally ++ public fun setTime(timeMillis: Long): Long = definedExternally ++ public fun setUTCDate(day: Int): Long = definedExternally ++ public fun setUTCFullYear(year: Int, ++ month: Int, ++ day: Int): Long = definedExternally ++ public fun setUTCHours(hours: Int, ++ minutes: Int = definedExternally, ++ seconds: Int = definedExternally, ++ millis: Int): Long = definedExternally ++ public fun setUTCMilliseconds(millis: Int): Long = definedExternally ++ public fun setUTCMinutes(minutes: Int, ++ seconds: Int = definedExternally, ++ millis: Int = definedExternally): Long = definedExternally ++ public fun setUTCMonth(month: Int, ++ day: Int = definedExternally): Long = definedExternally ++ public fun setUTCSeconds(seconds: Int, ++ millis: Int = definedExternally): Long = definedExternally ++ ++ @Deprecated(""Be aware that this feature may cease to work at any time."", ReplaceWith(""setFullYear"")) ++ public fun setYear(year: Int): Long = definedExternally ++ ++ ++ ++ public fun toDateString(): String = definedExternally ++ @Deprecated(""Be aware that this feature may cease to work at any time."", ReplaceWith(""toUTCString"")) ++ public fun toGMTString(): String = definedExternally ++ public fun toISOString(): String = definedExternally ++ public fun toJSON(): String = definedExternally ++ public fun toLocaleDateString(locales: dynamic = definedExternally, /* String | Array */ ++ options: dynamic = definedExternally): String = definedExternally ++ public fun toLocaleString(locales: dynamic = definedExternally, /* String | Array */ ++ options: dynamic = definedExternally): String = definedExternally ++ public fun toLocaleTimeString(locales: dynamic = definedExternally, /* String | Array */ ++ options: dynamic = definedExternally): String = definedExternally ++ public override fun toString(): String = definedExternally ++ public fun toTimeString(): String = definedExternally ++ public fun toUTCString(): String = definedExternally ++ public fun valueOf(): Long = definedExternally ++ ++ companion object { ++ fun now(): Long = definedExternally",I think return type should not be `Long` here since it's not native JS type and it's emulated in Kotlin. Probably it should be `Number` or `Double`.,2017-07-24 19:20:45 +343,"@@ -4,66 +4,121 @@ import java.util.Timer + import java.util.TimerTask + import java.util.Date + ++/** ++ * Schedules an [action] to be executed after the specified [delay] (expressed in milliseconds). ++ */ + public fun Timer.schedule(delay: Long, action: TimerTask.() -> Unit): TimerTask { + val task = timerTask(action) + schedule(task, delay) + return task + } + ++/** ++ * Schedules an [action] to be executed at the specified [time]. ++ */ + public fun Timer.schedule(time: Date, action: TimerTask.() -> Unit): TimerTask { + val task = timerTask(action) + schedule(task, time) + return task + } + ++/** ++ * Schedules an [action] to be executed periodically, starting after the specified [delay] (expressed ++ * in milliseconds) and with the interval of [period] milliseconds between the end of the previous task ++ * and the start of the next one. ++ */ + public fun Timer.schedule(delay: Long, period: Long, action: TimerTask.() -> Unit): TimerTask { + val task = timerTask(action) + schedule(task, delay, period) + return task + } + ++/** ++ * Schedules an [action] to be executed periodically, starting at the specified [time] and with the ++ * interval of [period] milliseconds between the end of the previous task and the start of the next one. ++ */ + public fun Timer.schedule(time: Date, period: Long, action: TimerTask.() -> Unit): TimerTask { + val task = timerTask(action) + schedule(task, time, period) + return task + } + ++/** ++ * Schedules an [action] to be executed periodically, starting after the specified [delay] (expressed ++ * in milliseconds) and with the interval of [period] milliseconds between the start of the previous task ++ * and the start of the next one. ++ */ + public fun Timer.scheduleAtFixedRate(delay: Long, period: Long, action: TimerTask.() -> Unit): TimerTask { + val task = timerTask(action) + scheduleAtFixedRate(task, delay, period) + return task + } + ++/** ++ * Schedules an [action] to be executed periodically, starting at the specified [time] and with the ++ * interval of [period] milliseconds between the start of the previous task and the start of the next one. ++ */ + public fun Timer.scheduleAtFixedRate(time: Date, period: Long, action: TimerTask.() -> Unit): TimerTask { + val task = timerTask(action) + scheduleAtFixedRate(task, time, period) + return task + } + ++/** ++ * Creates a timer that executes the specified [action] periodically, starting after the specified [initialDelay] ++ * (expressed in milliseconds) and with the interval of [period] milliseconds between the end of the previous task ++ * and the start of the next one. ++ * ++ * @param name the name to use for the thread which is running the timer. ++ * @param daemon if true, the thread is started as a daemon thread (the VM will exit when only daemon threads are running) ++ */ + public fun timer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.() -> Unit): Timer { + val timer = if (name == null) Timer(daemon) else Timer(name, daemon) + timer.schedule(initialDelay, period, action) + return timer + } + ++/** ++ * Creates a timer that executes the specified [action] periodically, starting at the specified [startAt] date ++ * and with the interval of [period] milliseconds between the end of the previous task and the start of the next one. ++ * ++ * @param name the name to use for the thread which is running the timer. ++ * @param daemon if true, the thread is started as a daemon thread (the VM will exit when only daemon threads are running) ++ */ + public fun timer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, action: TimerTask.() -> Unit): Timer { + val timer = if (name == null) Timer(daemon) else Timer(name, daemon) + timer.schedule(startAt, period, action) + return timer + } + ++/** ++ * Creates a timer that executes the specified [action] periodically, starting after the specified [initialDelay] ++ * (expressed in milliseconds) and with the interval of [period] milliseconds between the start of the previous task ++ * and the start of the next one. ++ * ++ * @param name the name to use for the thread which is running the timer. ++ * @param daemon if true, the thread is started as a daemon thread (the VM will exit when only daemon threads are running) ++ */ + public fun fixedRateTimer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.() -> Unit): Timer { + val timer = if (name == null) Timer(daemon) else Timer(name, daemon) + timer.scheduleAtFixedRate(initialDelay, period, action) + return timer + } + ++/** ++ * Creates a timer that executes the specified [action] periodically, starting at the specified [startAt] date ++ * and with the interval of [period] milliseconds between the start of the previous task and the start of the next one. ++ * ++ * @param name the name to use for the thread which is running the timer. ++ * @param daemon if true, the thread is started as a daemon thread (the VM will exit when only daemon threads are running) ++ */ + public fun fixedRateTimer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, action: TimerTask.() -> Unit): Timer { + val timer = if (name == null) Timer(daemon) else Timer(name, daemon) + timer.scheduleAtFixedRate(startAt, period, action) + return timer + } + ++deprecated(""Use the built-in SAM conversion instead"")","Shouldn't we update usages in this file to invoke TimerTask constructor directly? +",2015-03-12 15:00:37 +949,"@@ -4,7 +4,7 @@ object A { + ""text3"" + + +- val TEXT2 = ""text1\n"" +- + ""text2\n"" +- + ""text3"" ++ val TEXT2 = (""text1\n""","If I were you, I would reduce space from 2 to 1 line. I think one is enough to make this object readable.",2017-08-04 08:42:49 +942,"@@ -4,8 +4,8 @@ internal class C { + fun foo(): Int { + KotlinObject.property1 = 1 + KotlinObject.property2 = 2 +- return KotlinObject.foo() + ++ return (KotlinObject.foo() +",The parentheses are only required if the line break is before the operator. In this case they should not be added.,2017-08-03 10:41:40 +258,"@@ -40,10 +40,224 @@ import org.gradle.api.UnknownDomainObjectException + import org.gradle.api.initialization.dsl.ScriptHandler + import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper + import javax.inject.Inject ++import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile ++import org.gradle.api.tasks.Copy ++import org.gradle.api.file.SourceDirectorySet ++import kotlin.properties.Delegates ++import org.gradle.api.tasks.Delete ++import org.codehaus.groovy.runtime.MethodClosure ++import org.jetbrains.kotlin.gradle.tasks.RewritePathsInSourceMap ++import groovy.lang.Closure + + val DEFAULT_ANNOTATIONS = ""org.jebrains.kotlin.gradle.defaultAnnotations"" + +-open class KotlinPlugin [Inject] (val scriptHandler: ScriptHandler): Plugin { ++ ++abstract class KotlinSourceSetProcessor(val project: ProjectInternal, ++ val javaBasePlugin: JavaBasePlugin, ++ val sourceSet: SourceSet, ++ val pluginName: String, ++ val compileTaskNameSuffix: String, ++ val taskDescription: String, ++ val compilerClass: Class) { ++ abstract protected fun doTargetSpecificProcessing() ++ val logger = Logging.getLogger(this.javaClass) ++ ++ protected val sourceSetName: String = sourceSet.getName() ++ protected val sourceRootDir: String = ""src/${sourceSetName}/kotlin"" ++ protected val absoluteSourceRootDir: String = project.getProjectDir().getPath() + ""/"" + sourceRootDir ++ protected val kotlinSourceSet: KotlinSourceSet? by Delegates.lazy { createKotlinSourceSet() } ++ protected val kotlinDirSet: SourceDirectorySet? by Delegates.lazy { createKotlinDirSet() } ++ protected val kotlinTask: T by Delegates.lazy { createKotlinCompileTask() } ++ protected val kotlinTaskName: String by Delegates.lazy { kotlinTask.getName() } ++ ++ public fun run() { ++ if (kotlinSourceSet == null || kotlinDirSet == null) { ++ return ++ } ++ addSourcesToKotlinDirSet() ++ commonTaskConfiguration() ++ doTargetSpecificProcessing() ++ } ++ ++ open protected fun createKotlinSourceSet(): KotlinSourceSet? = ++ if (sourceSet is HasConvention) { ++ logger.debug(""Creating KotlinSourceSet for source set ${sourceSet}"") ++ val kotlinSourceSet = KotlinSourceSetImpl(sourceSet.getName(), project.getFileResolver()) ++ sourceSet.getConvention().getPlugins().put(pluginName, kotlinSourceSet) ++ kotlinSourceSet ++ } else { ++ null ++ } ++ ++ open protected fun createKotlinDirSet(): SourceDirectorySet? { ++ val srcDir = project.file(sourceRootDir) ++ logger.debug(""Creating Kotlin SourceDirectorySet for source set ${kotlinSourceSet} with src dir ${srcDir}"") ++ val kotlinDirSet = kotlinSourceSet?.getKotlin() ++ kotlinDirSet?.srcDir(srcDir) ++ return kotlinDirSet ++ } ++ ++ open protected fun addSourcesToKotlinDirSet() { ++ logger.debug(""Adding Kotlin SourceDirectorySet ${kotlinDirSet} to source set ${sourceSet}"") ++ sourceSet.getAllJava()?.source(kotlinDirSet) ++ sourceSet.getAllSource()?.source(kotlinDirSet) ++ sourceSet.getResources()?.getFilter()?.exclude(KSpec({ elem -> ++ kotlinDirSet!!.contains(elem.getFile()) ++ })) ++ } ++ ++ open protected fun createKotlinCompileTask(): T { ++ val name = sourceSet.getCompileTaskName(compileTaskNameSuffix) ++ logger.debug(""Creating kotlin compile task $name with class $compilerClass"") ++ return project.getTasks().create(name, compilerClass) ++ } ++ ++ open protected fun commonTaskConfiguration() { ++ javaBasePlugin.configureForSourceSet(sourceSet, kotlinTask) ++ kotlinTask.setDescription(taskDescription) ++ kotlinTask.source(kotlinDirSet) ++ } ++} ++ ++class Kotlin2JvmSourceSetProcessor( ++ project: ProjectInternal, ++ javaBasePlugin: JavaBasePlugin, ++ sourceSet: SourceSet, ++ val scriptHandler: ScriptHandler) ++: KotlinSourceSetProcessor( ++ project, javaBasePlugin, sourceSet, ++ pluginName = ""kotlin"", ++ compileTaskNameSuffix = ""kotlin"", ++ taskDescription = ""Compiles the $sourceSet.kotlin."", ++ compilerClass = javaClass()) { ++ ++ override fun doTargetSpecificProcessing() { ++ // store kotlin classes in separate directory. They will serve as class-path to java compiler ++ val kotlinOutputDir = File(project.getBuildDir(), ""kotlin-classes/${sourceSetName}"") ++ kotlinTask.kotlinDestinationDir = kotlinOutputDir ++ ++ val javaTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile? ++ ++ if (javaTask != null) { ++ javaTask.dependsOn(kotlinTaskName) ++ val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir); ++ javaTask.setClasspath(javacClassPath) ++ } ++ } ++} ++ ++ ++class Kotlin2JsSourceSetProcessor( ++ project: ProjectInternal, ++ javaBasePlugin: JavaBasePlugin, ++ sourceSet: SourceSet, ++ val scriptHandler: ScriptHandler ++) : KotlinSourceSetProcessor( ++ project, javaBasePlugin, sourceSet, ++ pluginName = ""kotlin2js"", ++ taskDescription = ""Compiles the kotlin sources in $sourceSet to JavaScript."", ++ compileTaskNameSuffix = ""kotlin2Js"", ++ compilerClass = javaClass()) { ++ val copyKotlinJsTaskName = sourceSet.getTaskName(""copy"", ""kotlinJs"") ++ val clean = project.getTasks().findByName(""clean"") ++ val compileJava = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile?","Why we need javaTask? +",2014-11-12 11:52:19 +261,"@@ -40,10 +40,224 @@ import org.gradle.api.UnknownDomainObjectException + import org.gradle.api.initialization.dsl.ScriptHandler + import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper + import javax.inject.Inject ++import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile ++import org.gradle.api.tasks.Copy ++import org.gradle.api.file.SourceDirectorySet ++import kotlin.properties.Delegates ++import org.gradle.api.tasks.Delete ++import org.codehaus.groovy.runtime.MethodClosure ++import org.jetbrains.kotlin.gradle.tasks.RewritePathsInSourceMap ++import groovy.lang.Closure + + val DEFAULT_ANNOTATIONS = ""org.jebrains.kotlin.gradle.defaultAnnotations"" + +-open class KotlinPlugin [Inject] (val scriptHandler: ScriptHandler): Plugin { ++ ++abstract class KotlinSourceSetProcessor(val project: ProjectInternal, ++ val javaBasePlugin: JavaBasePlugin, ++ val sourceSet: SourceSet, ++ val pluginName: String, ++ val compileTaskNameSuffix: String, ++ val taskDescription: String, ++ val compilerClass: Class) { ++ abstract protected fun doTargetSpecificProcessing() ++ val logger = Logging.getLogger(this.javaClass) ++ ++ protected val sourceSetName: String = sourceSet.getName() ++ protected val sourceRootDir: String = ""src/${sourceSetName}/kotlin"" ++ protected val absoluteSourceRootDir: String = project.getProjectDir().getPath() + ""/"" + sourceRootDir ++ protected val kotlinSourceSet: KotlinSourceSet? by Delegates.lazy { createKotlinSourceSet() } ++ protected val kotlinDirSet: SourceDirectorySet? by Delegates.lazy { createKotlinDirSet() } ++ protected val kotlinTask: T by Delegates.lazy { createKotlinCompileTask() } ++ protected val kotlinTaskName: String by Delegates.lazy { kotlinTask.getName() } ++ ++ public fun run() { ++ if (kotlinSourceSet == null || kotlinDirSet == null) { ++ return ++ } ++ addSourcesToKotlinDirSet() ++ commonTaskConfiguration() ++ doTargetSpecificProcessing() ++ } ++ ++ open protected fun createKotlinSourceSet(): KotlinSourceSet? = ++ if (sourceSet is HasConvention) { ++ logger.debug(""Creating KotlinSourceSet for source set ${sourceSet}"") ++ val kotlinSourceSet = KotlinSourceSetImpl(sourceSet.getName(), project.getFileResolver()) ++ sourceSet.getConvention().getPlugins().put(pluginName, kotlinSourceSet) ++ kotlinSourceSet ++ } else { ++ null ++ } ++ ++ open protected fun createKotlinDirSet(): SourceDirectorySet? { ++ val srcDir = project.file(sourceRootDir) ++ logger.debug(""Creating Kotlin SourceDirectorySet for source set ${kotlinSourceSet} with src dir ${srcDir}"") ++ val kotlinDirSet = kotlinSourceSet?.getKotlin() ++ kotlinDirSet?.srcDir(srcDir) ++ return kotlinDirSet ++ } ++ ++ open protected fun addSourcesToKotlinDirSet() { ++ logger.debug(""Adding Kotlin SourceDirectorySet ${kotlinDirSet} to source set ${sourceSet}"") ++ sourceSet.getAllJava()?.source(kotlinDirSet) ++ sourceSet.getAllSource()?.source(kotlinDirSet) ++ sourceSet.getResources()?.getFilter()?.exclude(KSpec({ elem -> ++ kotlinDirSet!!.contains(elem.getFile()) ++ })) ++ } ++ ++ open protected fun createKotlinCompileTask(): T { ++ val name = sourceSet.getCompileTaskName(compileTaskNameSuffix) ++ logger.debug(""Creating kotlin compile task $name with class $compilerClass"") ++ return project.getTasks().create(name, compilerClass) ++ } ++ ++ open protected fun commonTaskConfiguration() { ++ javaBasePlugin.configureForSourceSet(sourceSet, kotlinTask) ++ kotlinTask.setDescription(taskDescription) ++ kotlinTask.source(kotlinDirSet) ++ } ++} ++ ++class Kotlin2JvmSourceSetProcessor( ++ project: ProjectInternal, ++ javaBasePlugin: JavaBasePlugin, ++ sourceSet: SourceSet, ++ val scriptHandler: ScriptHandler) ++: KotlinSourceSetProcessor( ++ project, javaBasePlugin, sourceSet, ++ pluginName = ""kotlin"", ++ compileTaskNameSuffix = ""kotlin"", ++ taskDescription = ""Compiles the $sourceSet.kotlin."", ++ compilerClass = javaClass()) { ++ ++ override fun doTargetSpecificProcessing() { ++ // store kotlin classes in separate directory. They will serve as class-path to java compiler ++ val kotlinOutputDir = File(project.getBuildDir(), ""kotlin-classes/${sourceSetName}"") ++ kotlinTask.kotlinDestinationDir = kotlinOutputDir ++ ++ val javaTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile? ++ ++ if (javaTask != null) { ++ javaTask.dependsOn(kotlinTaskName) ++ val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir); ++ javaTask.setClasspath(javacClassPath) ++ } ++ } ++} ++ ++ ++class Kotlin2JsSourceSetProcessor( ++ project: ProjectInternal, ++ javaBasePlugin: JavaBasePlugin, ++ sourceSet: SourceSet, ++ val scriptHandler: ScriptHandler ++) : KotlinSourceSetProcessor( ++ project, javaBasePlugin, sourceSet, ++ pluginName = ""kotlin2js"", ++ taskDescription = ""Compiles the kotlin sources in $sourceSet to JavaScript."", ++ compileTaskNameSuffix = ""kotlin2Js"", ++ compilerClass = javaClass()) { ++ val copyKotlinJsTaskName = sourceSet.getTaskName(""copy"", ""kotlinJs"") ++ val clean = project.getTasks().findByName(""clean"") ++ val compileJava = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile? ++ ++ val defaultKotlinDestinationDir = File(project.getBuildDir(), ""kotlin2js/${sourceSetName}"") ++ private fun kotlinTaskDestinationDir(): File? = kotlinTask.kotlinDestinationDir ++ private fun kotlinJsDestinationDir(): File? = if (kotlinTask.outputFile() == null) { ++ null ++ } else { ++ File(kotlinTask.outputFile()).directory ++ } ++ ++ private fun copyKotlinJsTaskOutput(): String? = if (kotlinJsDestinationDir() == null) { ++ null ++ } else { ++ val copyTask = project.getTasks().getByName(copyKotlinJsTaskName) as Copy ++ ""${copyTask.getDestinationDir()}/kotlin.js"" ++ } ++ ++ private fun kotlinSourcePathsForSourceMap() = sourceSet.getAllSource() ++ .map { it.path } ++ .filter { it.endsWith("".kt"") } ++ .map { it.replace(absoluteSourceRootDir, kotlinTask.sourceMapDestinationDir().getPath()) } ++ ++ private fun shouldGenerateSourceMap() = kotlinTask.kotlinOptions.sourceMap ++ ++ override fun doTargetSpecificProcessing() { ++ val version = project.getProperties()[""kotlin.gradle.plugin.version""] as String ++ val jsLibraryJar = GradleUtils(scriptHandler).resolveDependencies(""org.jetbrains.kotlin:kotlin-js-library:$version"").map { it.getAbsolutePath() }[0] ++ ++ kotlinTask.kotlinOptions.libraryFiles = array(jsLibraryJar) ++ kotlinTask.kotlinDestinationDir = defaultKotlinDestinationDir ++ ++ compileJava?.dependsOn(kotlinTaskName) ++ clean?.dependsOn(""clean"" + kotlinTaskName.capitalize()) ++ ++ createCopyKotlinJsTask(jsLibraryJar) ++ createCopyKotlinSourcesForSourceMapTask()","I think we should not be able to copy source files. +",2014-11-13 17:05:10 +729,"@@ -40,9 +41,12 @@ class KotlinClassFinderTest : KotlinTestWithEnvironmentManagement() { + val environment = createEnvironment(tmpdir) + val project = environment.project + ++ val classFinder = createClassFinder(project)","Here you also should create your own separate test, and leave the old one as is. ",2017-04-05 15:37:43 +494,"@@ -41,12 +41,21 @@ + import org.jetbrains.kotlin.utils.KotlinPaths; + import org.jetbrains.kotlin.utils.PathUtil; + import org.junit.Assert; ++import org.junit.Before; + import org.junit.Test; + + import java.util.Collections; + import java.util.List; + + public class ScriptTest { ++ ++ //@Before ++ //public void setUp() throws Exception { ++ // // set to false if not present or set to true or unknown (empty considered true) ++ // if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY)?.let { it.toBooleanLenient() ?: true } ?: true ) ++ // System.setProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, ""false"") ++ //} ++","Why is this needed here? +",2015-11-28 17:25:08 +7,"@@ -410,6 +410,9 @@","ignore this file +",2012-05-24 14:21:07 +225,"@@ -4118,6 +4118,59 @@ public void testTypesAlreadyImplicit() throws Exception { + + } + ++ @TestMetadata(""idea/testData/intentions/invertIfCondition"") ++ public static class InvertIfCondition extends AbstractCodeTransformationTest { ++ public void testAllFilesPresentInInvertIfCondition() throws Exception { ++ JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), ""org.jetbrains.jet.generators.tests.TestsPackage"", new File(""idea/testData/intentions/invertIfCondition""), Pattern.compile(""^(.+)\\.kt$""), true); ++ } ++ ++ @TestMetadata(""binaryExpression.kt"") ++ public void testBinaryExpression() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/binaryExpression.kt""); ++ } ++ ++ @TestMetadata(""booleanLiteral.kt"") ++ public void testBooleanLiteral() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/booleanLiteral.kt""); ++ } ++ ++ @TestMetadata(""forLoopWithMultipleExpressions.kt"") ++ public void testForLoopWithMultipleExpressions() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt""); ++ } ++ ++ @TestMetadata(""functionWithReturnExpression.kt"") ++ public void testFunctionWithReturnExpression() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt""); ++ } ++ ++ @TestMetadata(""ifExpressionInsideForLoop.kt"") ++ public void testIfExpressionInsideForLoop() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt""); ++ } ++ ++ @TestMetadata(""ifExpressionWithReturn.kt"") ++ public void testIfExpressionWithReturn() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt""); ++ } ++ ++ @TestMetadata(""invertableOperator.kt"") ++ public void testInvertableOperator() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/invertableOperator.kt""); ++ } ++ ++ @TestMetadata(""negatedExpression.kt"") ++ public void testNegatedExpression() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/negatedExpression.kt""); ++ } ++ ++ @TestMetadata(""simple.kt"") ++ public void testSimple() throws Exception { ++ doTestInvertIfCondition(""idea/testData/intentions/invertIfCondition/simple.kt""); ++ } ++ ++ } ++ ","Please add some tests for the cases where ""if"" is used as an expression, like +`val t = if (a > 0) a else -a` +Combinations of valued ifs with returns and other ""jumps"" is of particular interest, e.g. `return if ...` or `val t = if (a > 0) a else return 0`, etc. +",2014-05-03 10:55:02 +88,"@@ -414,6 +414,14 @@ class CollectionTest { + expect(arrayList(2, 3, 1)) { list } + } + ++ test fun sum() { ++ expect(0) {ArrayList().sum()} ++ expect(14) {arrayListOf(2,3,9).sum()} ++ expect(3.0) {arrayListOf(1.0,2.0).sum()} ++ expect(3000000000000) {arrayListOf(1000000000000,2000000000000).sum()}","Formatting: space after comma +",2013-11-27 07:35:41 +675,"@@ -423,6 +423,13 @@ public header inline fun >> CharSequen + public header inline fun >> CharSequence.groupByTo(destination: M, keySelector: (Char) -> K, valueTransform: (Char) -> V): M + + /** ++ * Creates a [Grouping] source from a char sequence to be used later with one of group-and-fold operations ++ * using the specified [keySelector] function to extract a key from each character. ++ */ ++@SinceKotlin(""1.1"") ++public header inline fun CharSequence.groupingBy(crossinline keySelector: (Char) -> K): Grouping",why there is specialization here? the implementations look the same,2016-12-29 12:55:04 +603,"@@ -424,6 +425,24 @@ class Converter private constructor( + } + } + ++ ++ private fun specialAnnotationPropertyCases(field: PsiField): Annotations { ++ val javaSerializableInterface = PsiType.getTypeByName(""java.io.Serializable"", project, GlobalSearchScope.allScope(project)).resolve()","It's a minor issue, but the correct way is to use `field.getResolveScope()` instead of `allScope` here. Otherwise you may get incorrect results if the project uses multiple JDKs in different modules. +",2016-09-12 08:56:16 +688,"@@ -428,4 +428,37 @@ class KotlinGradleIT: BaseGradleIT() { + assertSuccessful() + } + } ++ ++ @Test ++ fun testGradleJavaIcWorking() { ++ val project = Project(""kotlinJavaProject"", ""2.14.1"")","What about newer Gradle versions? +Btw, it would be interesting to test if Java compile avoidance works in this case with the Gradle 3.4 (in other words that Java is not compiled if Kotlin public API is not changed). ",2017-03-14 10:01:02 +278,"@@ -43,6 +83,15 @@ public trait MutableListIterator : ListIterator, MutableIterator { + + // Modification Operations + override fun remove(): Unit ++ ++ /** ++ * Replaces the last element returned by [next] or [previous] with the specified element [e]. ++ */ + public fun set(e: T): Unit ++ ++ /** ++ * Adds the specified element [e] into the underlying collection immediately before the element that would be ++ * returned by [next].","Will it affect what is returned next? Unclear from the text. What if previous was called? +",2015-02-09 15:36:05 +838,"@@ -439,6 +443,13 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping + context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(element as KtNullableType)) + } + checkTypeCompatibility(context, targetType, subjectType, typeReferenceAfterIs) ++ if (!subjectType.containsError() && !targetType.containsError() && subjectType.isSubtypeOf(targetType)) {","Note that this isn't correct for platform types (see https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types) + +Currently there will be warning for case like this: +``` +// Java +class A { + static A create() { return null; } +} +-- +// Kotlin +fun test() { + A.create() is A // false warning +} +```",2017-05-02 18:40:04 +959,"@@ -44,7 +44,7 @@ object MakeVisibleFactory : KotlinIntentionActionsFactory() { + + val module = DescriptorUtils.getContainingModule(descriptor) + val targetVisibilities = when (descriptor.visibility) { +- PRIVATE, INVISIBLE_FAKE -> if (module != usageModule) listOf(PUBLIC) else listOf(PUBLIC, INTERNAL) ++ PRIVATE, INVISIBLE_FAKE -> if (module != usageModule) listOf(PUBLIC) else listOf(PUBLIC, INTERNAL, PROTECTED)","It's not so easy, because `protected` should not be offered if member is referenced not from a subclass. Please add necessary checks here and such a test.",2017-08-14 10:29:34 +647,"@@ -45,15 +46,7 @@ class JoinBlockIntoSingleStatementHandler : JoinRawLinesHandlerDelegate { + // if outer if has else-branch and inner does not have it, do not remove braces otherwise else-branch will belong to different if!","I can't unify the check because while the intention is simply not available, the join handler still has to go into this branch. +",2016-10-21 17:36:22 +492,"@@ -45,6 +47,13 @@ public abstract class AbstractReplInterpreterTest : UsefulTestCase() { + + private data class OneLine(val code: String, val expected: String) + ++ override fun setUp() { ++ super.setUp() ++ // set to false if not present or set to true or unknown (empty considered true) ++ if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY)?.let { it.toBooleanLenient() ?: true } ?: true )","This could be written as + +``` +if (KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.systemPropertyAsBooleanOrTrueOtherwise(negate = false)) { +``` +",2015-11-27 18:22:30 +695,"@@ -45,6 +49,37 @@ import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer + import org.jetbrains.kotlin.resolve.lazy.ResolveSession + import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory + ++private fun StorageComponentContainer.configureJavaTopDownAnalysisWithJavac( ++ moduleContentScope: GlobalSearchScope, ++ project: Project, ++ lookupTracker: LookupTracker",I think it's better to remove this function and add boolean flag `useJavac` to the next one instead. The code is mostly the same,2017-04-05 12:23:40 +550,"@@ -454,3 +454,17 @@ fun checkReservedPrefixWord(sink: DiagnosticSink, element: PsiElement, word: Str + } + } + ++fun KtNameReferenceExpression.getPrimaryConstructorParameterWithSameName(): KtParameter? {","I think this is far too specific to live in a general PSI utlilities class; I'd move it into the quickfix file. +",2016-04-28 08:57:16 +551,"@@ -454,3 +454,17 @@ fun checkReservedPrefixWord(sink: DiagnosticSink, element: PsiElement, word: Str + } + } + ++fun KtNameReferenceExpression.getPrimaryConstructorParameterWithSameName(): KtParameter? { ++ return getPrimaryConstructorParameterWithName(getReferencedName()) ++} ++ ++private fun KtElement.getPrimaryConstructorParameterWithName(name: String): KtParameter? {","The name of this function doesn't describe what it does. A more descriptive name would be ""findContainingClassConstructorParameterWithName"" (which is long enough to hint that it may be better to split the logic: a function to generate a sequence of outer classes for a class and a single-line call to find the parameter of the class by name). +",2016-04-28 09:00:23 +263,"@@ -46,15 +84,91 @@ public val File.extension: String + } + + /** ++ * Replaces all separators in the string used to separate directories with system ones and returns the resulting string. ++ */ ++public fun String.separatorsToSystem(): String { ++ val otherSep = if (File.separator == ""/"") ""\\"" else ""/"" ++ return replace(otherSep, File.separator) ++} ++ ++/** ++ * Replaces all path separators in the string with system ones and returns the resulting string. ++ */ ++public fun String.pathSeparatorsToSystem(): String { ++ val otherSep = if (File.pathSeparator == "":"") "";"" else "":"" ++ return replace(otherSep, File.pathSeparator) ++} ++ ++/** ++ * Replaces path and directories separators with corresponding system ones and returns the resulting string. ++ */ ++public fun String.allSeparatorsToSystem(): String { ++ return separatorsToSystem().pathSeparatorsToSystem() ++} ++ ++/** ++ * Returns a pathname of this file with all path separators replaced with File.pathSeparator ++ */ ++public fun File.separatorsToSystem(): String { ++ return toString().separatorsToSystem() ++} ++ ++/** ++ * Returns file's name without an extension. ++ */ ++public val File.nameWithoutExtension: String ++ get() = name.substringBeforeLast(""."") ++ ++/** + * Returns true if the given file is in the same directory or a descendant directory + */ + public fun File.isDescendant(file: File): Boolean { + return file.directory.canonicalPath.startsWith(directory.canonicalPath) + } +- + /** +- * Returns the relative path of the given descendant of this file if it is a descendant ++ * Returns path of this file relatively to the given directory. ++ * Note that the base file is treated as a directory. ++ * If this file matches the base directory, then ""."" will be returned. + */ ++public fun File.relativeTo(base: File): String {","Shouldn't it return File instead? +",2014-11-26 14:52:46 +262,"@@ -46,15 +84,91 @@ public val File.extension: String + } + + /** ++ * Replaces all separators in the string used to separate directories with system ones and returns the resulting string. ++ */ ++public fun String.separatorsToSystem(): String { ++ val otherSep = if (File.separator == ""/"") ""\\"" else ""/"" ++ return replace(otherSep, File.separator) ++} ++ ++/** ++ * Replaces all path separators in the string with system ones and returns the resulting string. ++ */ ++public fun String.pathSeparatorsToSystem(): String { ++ val otherSep = if (File.pathSeparator == "":"") "";"" else "":"" ++ return replace(otherSep, File.pathSeparator) ++} ++ ++/** ++ * Replaces path and directories separators with corresponding system ones and returns the resulting string. ++ */ ++public fun String.allSeparatorsToSystem(): String { ++ return separatorsToSystem().pathSeparatorsToSystem() ++} ++ ++/** ++ * Returns a pathname of this file with all path separators replaced with File.pathSeparator ++ */ ++public fun File.separatorsToSystem(): String { ++ return toString().separatorsToSystem() ++} ++ ++/** ++ * Returns file's name without an extension. ++ */ ++public val File.nameWithoutExtension: String ++ get() = name.substringBeforeLast(""."") ++ ++/** + * Returns true if the given file is in the same directory or a descendant directory + */ + public fun File.isDescendant(file: File): Boolean { + return file.directory.canonicalPath.startsWith(directory.canonicalPath) + } +- + /** +- * Returns the relative path of the given descendant of this file if it is a descendant ++ * Returns path of this file relatively to the given directory. ++ * Note that the base file is treated as a directory. ++ * If this file matches the base directory, then ""."" will be returned. + */ ++public fun File.relativeTo(base: File): String { ++ val thisCanonical = canonicalPath ++ val baseCanonical = base.canonicalPath ++ if (thisCanonical.equals(baseCanonical)) { ++ return ""."" ++ } ++ ++ fun String.longestCommonPrefixLen(o: String): Int { ++ var i = 0 ++ val len = length ++ val oLen = o.length ++ while (i < len && i < oLen && this[i] == o[i]) { ++ i++ ++ } ++ return i ++ } ++ ++ val commonPrefLen = thisCanonical.longestCommonPrefixLen(baseCanonical) ++ val thisSuffix = thisCanonical.substring(commonPrefLen + if (commonPrefLen == baseCanonical.length) 1 else 0) ++ val baseSuffix = baseCanonical.substring(commonPrefLen + if (commonPrefLen == thisCanonical.length) 1 else 0) ++ val separator = File.separator.charAt(0) ++ val ups = if (baseSuffix.isEmpty()) 0 else baseSuffix.count { it == separator } + 1 ++ val result = StringBuilder() ++ for (i in 1 .. ups) { ++ if (i != 1) { ++ result.append(separator) ++ } ++ result.append("".."") ++ } ++ if (commonPrefLen != thisCanonical.length) { ++ if (result.length() != 0) { ++ result.append(separator) ++ } ++ result.append(thisSuffix) ++ } ++ return result.toString() ++} ++ ++deprecated(""Use relativeTo() functin instead"")","typo: functin +",2014-11-26 14:52:24 +653,"@@ -46,7 +45,7 @@ internal fun MethodNode.getParametersInfo(containingClass: ClassNode): List descriptors = generateDelegatedMembers(classDescriptor, callableDescriptors); ++ outer: + for (CallableMemberDescriptor descriptor : descriptors) { ++ for (CallableMemberDescriptor existingDescriptor : classDescriptor.getAllCallableMembers()) {","Seems like you haven't updated from our trunk for a while. There is a conflict on this change. I'll resolve it manually, but in the future it would be a good idea to update frequently. +",2012-09-06 15:17:16 +922,"@@ -47,18 +66,23 @@ interface DependenciesResolver : @Suppress(""DEPRECATION"") ScriptDependenciesReso + } + } + ++// is File a could type to use here? ++// No way to get script name if file is not present, should add another property (val fileName: String) + interface ScriptContents { + val file: File? + val annotations: Iterable",Maybe use `Collection` here?,2017-07-25 11:17:04 +923,"@@ -47,18 +66,23 @@ interface DependenciesResolver : @Suppress(""DEPRECATION"") ScriptDependenciesReso + } + } + ++// is File a could type to use here? ++// No way to get script name if file is not present, should add another property (val fileName: String) + interface ScriptContents { + val file: File? + val annotations: Iterable + val text: CharSequence?",Why not `String?`?,2017-07-25 11:22:57 +921,"@@ -47,18 +66,23 @@ interface DependenciesResolver : @Suppress(""DEPRECATION"") ScriptDependenciesReso + } + } + ++// is File a could type to use here? ++// No way to get script name if file is not present, should add another property (val fileName: String) + interface ScriptContents { + val file: File? + val annotations: Iterable + val text: CharSequence? + ++ // nothing to discuss, for compatibility with previous version + @Deprecated(""Use DependenciesResolver interface"") + data class Position(val line: Int, val col: Int) + } + ++// ScriptReport -> ScriptDiagnostic + data class ScriptReport(val message: String, val severity: Severity = ScriptReport.Severity.ERROR, val position: Position? = null) { + data class Position(val startLine: Int, val startColumn: Int, val endLine: Int? = null, val endColumn: Int? = null) + enum class Severity { ERROR, WARNING, INFO, DEBUG } + } + +-fun ScriptDependencies.asSuccess(): ResolveResult.Success = ResolveResult.Success(this) +\ No newline at end of file ++// should we expose this helper? ++fun ScriptDependencies.asSuccess(): ResolutionResult.Success = ResolutionResult.Success(this)","I think, we should not",2017-07-25 11:14:51 +974,"@@ -47,6 +48,9 @@ public void updateInfo(@NotNull ValueArgument valueArgument, @NotNull DataFlowIn + throw new IllegalStateException(); + } + ++ @Override ++ public void updateResultInfo(@NotNull DataFlowInfo dataFlowInfo) { }",Should we throw here `IllegalStateException`?,2017-08-15 16:10:01 +138,"@@ -47,7 +47,7 @@ public class AddBracesIntention : JetSelfTargetingIntention("" + val jetBlockElement = element.findBlockInExpression(expressionKind)","[this is a dummy comment, please ignore it] +",2014-03-15 18:44:12 +769,"@@ -48,7 +48,7 @@ class JCClass(tree: T, + get() = tree.modifiers.isAbstract + + override val isStatic +- get() = outerClass?.isInterface ?: tree.modifiers.isStatic ++ get() = if (outerClass?.isInterface ?: false) true else tree.modifiers.isStatic","It's better to write here + +``` +(outerClass?.isInterface ?: false) || tree.modifiers.isStatic +```",2017-04-19 16:00:50 +626,"@@ -48,7 +48,8 @@ class ReplaceContainsIntention : SelfTargetingRangeIntention",Changed exception type to OutOfMemoryError,2016-11-22 20:38:41 +248,"@@ -5,20 +5,141 @@ import java.nio.charset.* + import java.util.* + + /** +- * Recursively process this file and all children with the given block ++ * Recursively process this file and all children with the given block. ++ * Note that if this file doesn't exist, then the block will be executed on it anyway. + */ + public fun File.recurse(block: (File) -> Unit): Unit { + block(this) +- val children = listFiles() +- if (children != null) { +- for (child in children) { +- child.recurse(block) ++ listFiles()?.forEach { it.recurse(block) } ++} ++ ++/** ++ * Stream allowing you to get all files that have the specified file as an ancestor in the depth-first order, ++ * including this file itself. ++ * ++ * If you specify a nonexistent file as a constructor parameter, IllegalArgumentException will be thrown. ++ */ ++public class TraverseStream(private val file: File) : Stream { ++ { ++ if (!file.exists()) { ++ throw IllegalArgumentException(""This file doesn't exist: $file"") ++ } ++ } ++ ++ override fun iterator(): Iterator = object : Iterator { ++ inner class Cursor(val files: Array, var pos: Int) { ++ val curFile: File ++ get() = files[pos] ++ } ++ ++ val cursors = arrayListOf(Cursor(array(file), 0)) ++ var childrenVisited = false ++ ++ fun prepareCursor() { ++ if (cursors.isEmpty()) { ++ return ++ } ++ var cursor = cursors.last!!","Do not use first/last properties, they will be removed. Use first()/last() methods. +",2014-11-06 11:47:00 +752,"@@ -5,6 +5,12 @@ + + + ++ ++ ++ ++ ++ ++",I think this should be dropped,2017-04-11 09:55:56 +556,"@@ -5,6 +5,12 @@ import org.junit.Test as test + + class StringBuilderTest { + ++ @test fun stringBuildWithInitialCapacity() { ++ val s = buildString(123) { ++ assertEquals(123, capacity())","This test won't compile in JS because there is no `StringBuilder.capacity` there. +To make this test JVM-only, move it to `StringBuilderJVMTest.kt` +",2016-05-17 17:42:06 +317,"@@ -5,8 +5,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock + import java.util.concurrent.CountDownLatch + + /** +- * Executes given calculation under lock +- * Returns result of the calculation ++ * Executes the given calculation under this lock.","calculation -> action +",2015-02-11 08:34:56 +438,"@@ -50,6 +52,8 @@ public String render(@NotNull ConflictingJvmDeclarationsData data) { + MAP.put(ErrorsJvm.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS, ""''jvmOverloads'' annotation has no effect for methods without default arguments""); + MAP.put(ErrorsJvm.OVERLOADS_ABSTRACT, ""''jvmOverloads'' annotation cannot be used on abstract methods""); + MAP.put(ErrorsJvm.OVERLOADS_PRIVATE, ""''jvmOverloads'' annotation has no effect on private and local declarations""); ++ MAP.put(ErrorsJvm.INAPPLICABLE_JVM_NAME, ""''jvmName ''annotation is not applicable to this declaration"");","Mistyped whitespace +",2015-08-25 12:51:43 +96,"@@ -51,7 +51,7 @@ + + http://www.w3.org/1999/xhtml + +- ++ ","This change is harmful, as well. +",2014-01-27 21:24:06 +941,"@@ -513,6 +513,16 @@ public static boolean areParenthesesNecessary( + return false; + } + ++ if (innerExpression instanceof KtBinaryExpression) { ++ PsiElement expr = innerExpression.getFirstChild(); ++ while (expr != null) { ++ if (expr instanceof PsiWhiteSpace && (expr.textContains('\n') || expr.textContains('\r'))) {","IntelliJ always normalizes text of files to use \n line breaks, the \r will never be there. Please remove it from the check.",2017-08-03 10:34:35 +645,"@@ -52,16 +52,16 @@ object MoveDeclarationsOutHelper { + val scope = LocalSearchScope(container) + val lastStatementOffset = statements[statements.size - 1].textRange.endOffset + +- for (statement in statements) { ++ statements.forEachIndexed { i, statement -> + if (needToDeclareOut(statement, lastStatementOffset, scope)) { + if (statement is KtProperty && statement.initializer != null) { +- var declaration = createVariableDeclaration(statement, generateDefaultInitializers) ++ val isLastStatement = i == statements.size - 1 ++ var declaration = createVariableAssignment(statement, generateDefaultInitializers, isLastStatement)","I don't think this code is structured well enough. You have three functions that do three sets of entirely different things based on a value of a boolean parameter. I think it's clearer to pull the check out to the top level and to avoid introducing the functions altogether. +",2016-10-18 18:58:03 +300,"@@ -52,37 +55,65 @@ public fun linkedMapOf(vararg values: Pair): LinkedHashMap { + return answer + } + +-/** Returns the [[Map]] if its not null otherwise it returns the empty [[Map]] */ ++/** ++ * Returns the [Map] if its not null, or the empty [Map] otherwise. ++ */ + public fun Map?.orEmpty() : Map + = if (this != null) this else emptyMap() + ++/** ++ * Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking ++ * whether an object is contained in the map. ++ */ + public fun Map.contains(key : K) : Boolean = containsKey(key) + +-/** Returns the key of the entry */ ++/** ++ * Allows to access the key of a map entry as a property. Equivalent to `getKey()`. ++ */ + public val Map.Entry.key: K + get() = getKey() + +-/** Returns the value of the entry */ ++/** ++ * Allows to access the value of a map entry as a property. Equivalent to `getValue()`. ++ */ + public val Map.Entry.value: V + get() = getValue() + +-/** Returns the key of the entry */ ++/** ++ * Returns the key of the map entry. This method allows to use multi-declarations when working with maps,","""Returns the key component of the map entry"" +",2015-02-09 16:03:34 +301,"@@ -52,37 +55,65 @@ public fun linkedMapOf(vararg values: Pair): LinkedHashMap { + return answer + } + +-/** Returns the [[Map]] if its not null otherwise it returns the empty [[Map]] */ ++/** ++ * Returns the [Map] if its not null, or the empty [Map] otherwise. ++ */ + public fun Map?.orEmpty() : Map + = if (this != null) this else emptyMap() + ++/** ++ * Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking ++ * whether an object is contained in the map. ++ */ + public fun Map.contains(key : K) : Boolean = containsKey(key) + +-/** Returns the key of the entry */ ++/** ++ * Allows to access the key of a map entry as a property. Equivalent to `getKey()`. ++ */ + public val Map.Entry.key: K + get() = getKey() + +-/** Returns the value of the entry */ ++/** ++ * Allows to access the value of a map entry as a property. Equivalent to `getValue()`. ++ */ + public val Map.Entry.value: V + get() = getValue() + +-/** Returns the key of the entry */ ++/** ++ * Returns the key of the map entry. This method allows to use multi-declarations when working with maps, ++ * for example: ++ * ``` ++ * for ((key, value) in map) { ++ * // do something with the key and the value ++ * } ++ * ``` ++ */ + public fun Map.Entry.component1(): K { + return getKey() + } + +-/** Returns the value of the entry */ ++/** ++ * Returns the value of the map entry. This method allows to use multi-declarations when working with maps,","""Returns the value component of the map entry"" +",2015-02-09 16:03:48 +302,"@@ -52,37 +55,65 @@ public fun linkedMapOf(vararg values: Pair): LinkedHashMap { + return answer + } + +-/** Returns the [[Map]] if its not null otherwise it returns the empty [[Map]] */ ++/** ++ * Returns the [Map] if its not null, or the empty [Map] otherwise. ++ */ + public fun Map?.orEmpty() : Map + = if (this != null) this else emptyMap() + ++/** ++ * Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking ++ * whether an object is contained in the map. ++ */ + public fun Map.contains(key : K) : Boolean = containsKey(key) + +-/** Returns the key of the entry */ ++/** ++ * Allows to access the key of a map entry as a property. Equivalent to `getKey()`. ++ */ + public val Map.Entry.key: K + get() = getKey() + +-/** Returns the value of the entry */ ++/** ++ * Allows to access the value of a map entry as a property. Equivalent to `getValue()`. ++ */ + public val Map.Entry.value: V + get() = getValue() + +-/** Returns the key of the entry */ ++/** ++ * Returns the key of the map entry. This method allows to use multi-declarations when working with maps, ++ * for example: ++ * ``` ++ * for ((key, value) in map) { ++ * // do something with the key and the value ++ * } ++ * ``` ++ */ + public fun Map.Entry.component1(): K { + return getKey() + } + +-/** Returns the value of the entry */ ++/** ++ * Returns the value of the map entry. This method allows to use multi-declarations when working with maps, ++ * for example: ++ * ``` ++ * for ((key, value) in map) { ++ * // do something with the key and the value ++ * } ++ * ``` ++ */ + public fun Map.Entry.component2(): V { + return getValue() + } + +-/** Converts entry to Pair with key being first component and value being second */ ++/** ++ * Converts entry to [Pair] with key being first component and value being second","This doc uses first/second _component_, while doc for mapOf/hashMapOf/… uses first/second _value_. Should use the same word. +",2015-02-09 16:05:14 +245,"@@ -527,10 +527,15 @@ static void generateConstructorWithoutParametersIfNeeded( + for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) { + Type paramType = state.getTypeMapper().mapType(parameterDescriptor.getType()); + pushDefaultValueOnStack(paramType, v); +- mask |= (1 << parameterDescriptor.getIndex()); ++ int i = parameterDescriptor.getIndex(); ++ if (i != 0 && i % Integer.SIZE == 0) { ++ v.iconst(mask); ++ mask = 0; ++ } ++ mask |= (1 << (parameterDescriptor.getIndex() % Integer.SIZE));","Use `i` here, introduced a few lines earlier +",2014-08-20 07:34:20 +244,"@@ -527,10 +527,15 @@ static void generateConstructorWithoutParametersIfNeeded( + for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) { + Type paramType = state.getTypeMapper().mapType(parameterDescriptor.getType()); + pushDefaultValueOnStack(paramType, v); +- mask |= (1 << parameterDescriptor.getIndex()); ++ int i = parameterDescriptor.getIndex(); ++ if (i != 0 && i % Integer.SIZE == 0) { ++ v.iconst(mask); ++ mask = 0; ++ } ++ mask |= (1 << (parameterDescriptor.getIndex() % Integer.SIZE)); + } + v.iconst(mask);","Should this `iconst` still be done if there's exactly `32*n` parameters? +",2014-08-20 07:33:41 +870,"@@ -53,14 +54,20 @@ class MovePropertyToConstructorIntention : + applyTo(property, null) + } + +- override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean = +- !element.isLocal +- && !element.hasDelegate() +- && element.getter == null +- && element.setter == null +- && !element.hasModifier(LATEINIT_KEYWORD) +- && element.getStrictParentOfType() is KtClass +- && (element.initializer?.isValidInConstructor() ?: true) ++ override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean { ++ fun KtProperty.isDeclaredInClass() : Boolean { ++ val parent = element.getStrictParentOfType() ++ return parent != null && !parent.isInterfaceClass()",Here it's also necessary to check that the `KtClassOrObject` is not an object declaration. I'll add this check.,2017-06-13 10:57:27 +341,"@@ -53,15 +82,15 @@ public fun thread(start: Boolean = true, daemon: Boolean = false, contextClassLo + + /** + * Allows you to use the executor as a function to","""Allows you"" - not good for docs. +",2015-03-12 14:58:09 +342,"@@ -53,15 +82,15 @@ public fun thread(start: Boolean = true, daemon: Boolean = false, contextClassLo + + /** + * Allows you to use the executor as a function to +- * execute the given block on the [[Executor]]. ++ * execute the given block on the [Executor]. + */ + public fun Executor.invoke(action: () -> Unit) { + execute(action) + } + + /** +- * Allows you to use the executor as a function to +- * execute the given block on the [[Executor]]. ++ * Allows you to use the executor service as a function to","Allows you. +",2015-03-12 14:58:17 +612,"@@ -538,6 +538,13 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter { + val qualifier = expression.qualifierExpression + + var identifier = Identifier.withNoPrototype(referenceName, isNullable) ++ ++ ++ if (expression.getContainingClass()?.getParentOfType(false).let { it != null && it == expression.qualifierExpression?.reference?.resolve() }) {","Why are you checking for `PsiField` specifically? Won't the same problem happen if the anonymous class is used as a local variable initializer? +",2016-09-22 10:04:48 +402,"@@ -538,6 +538,16 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ","Please do not put it under package `kotlin` as this is what's used by our stdlib, reflection and other public API. I propose `org.jetbrains.kotlin.com.google.protobuf` and `org.jetbrains.kotlin.javax.inject` +",2015-07-29 12:56:27 +419,"@@ -54,13 +62,14 @@ public static void runK2JvmCompiler( + CompilerSettings compilerSettings, + MessageCollector messageCollector, + CompilerEnvironment environment, +- File moduleFile, ++ Map incrementalCaches, File moduleFile,","It seems it is better to have one parameter per line. +",2015-08-20 14:10:55 +966,"@@ -54,6 +54,8 @@ enum class LanguageFeature( + InlineDefaultFunctionalParameters(KOTLIN_1_2), + SoundSmartCastsAfterTry(KOTLIN_1_2), + DeprecatedFieldForInvisibleCompanionObject(KOTLIN_1_2), ++ ContractEffects(KOTLIN_1_1), ++ CalledInPlaceEffect(KOTLIN_1_1),","Also, I suspect we require also the third feature, something like ""value analysis in conditions"". I have in mind checks like `if (1 == 2)`.",2017-08-15 15:46:32 +286,"@@ -548,7 +548,7 @@ public fun String.elementAt(index: Int): Char { + } + + /** +- * Returns first element ++ * Returns first element. Throws [NoSuchElementException] if the collection is empty.","Should it be `@throws` tag instead? +",2015-02-09 15:45:56 +123,"@@ -55,6 +55,15 @@ import com.intellij.psi.PsiPackage + import com.intellij.psi.PsiClass + import com.intellij.psi.PsiMember + import org.jetbrains.jet.lang.psi.JetNamedDeclaration ++import org.jetbrains.jet.lang.psi.JetExpressionImpl ++import org.jetbrains.jet.lang.psi.JetContainerNode ++import org.jetbrains.jet.lang.psi.JetWhileExpression ++import org.jetbrains.jet.lang.psi.JetDoWhileExpression ++import org.jetbrains.jet.lang.psi.JetForExpression ++import org.jetbrains.jet.lang.psi.JetIfExpression ++import org.jetbrains.jet.JetNodeTypes ++import com.intellij.lang.ASTNode","Some imports are unused here :) +",2014-03-04 16:01:37 +338,"@@ -55,6 +58,8 @@ public enum class InlineStrategy { + * receiving function are allowed to use non-local control flow statements. Lambdas which are called from + * a different execution context (for example, from an object contained in the receiving function) + * are restricted to local control flow statements. ++ * ++ * @property value the inlining options selected for this lambda.","""this lambda"" is unclear, may be ""options for annotated functional parameter""? +",2015-03-12 14:50:46 +392,"@@ -55,8 +55,8 @@ protected void postProcess(PsiFile createdElement, String templateName, Map ++ val gradleSupportsJavaIcWithClassesDirs = ParsedGradleVersion.parse(javaTask.project.gradle.gradleVersion)",I think that version checking should be performed before `upToDateWhen` callback is added,2017-03-14 09:55:46 +686,"@@ -551,8 +552,22 @@ internal open class KotlinAndroidPlugin( + } + + private fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractCompile, logger: Logger) { ++ // Gradle Java IC in older Gradle versions (before 2.14) cannot check .class directories updates. ++ // To make it work, reset the up-to-date status of compileJava with this flag. ++ kotlinTask.anyClassesCompiled = false ++ javaTask.outputs.upToDateWhen { task -> ++ val gradleSupportsJavaIcWithClassesDirs = ParsedGradleVersion.parse(javaTask.project.gradle.gradleVersion) ++ ?.let { it >= ParsedGradleVersion(2, 14) } ?: false ++ val kotlinClassesCompiled = kotlinTask.anyClassesCompiled ++ if (!gradleSupportsJavaIcWithClassesDirs && kotlinClassesCompiled) { ++ logger.info(""Marking $task out of date, because kotlin classes are changed"") ++ return@upToDateWhen false ++ } ++ true ++ } ++ + // Make Gradle check if the javaTask up-to-date based on the Kotlin classes +- javaTask.inputs.dir(kotlinTask.destinationDir!!) ++ javaTask.inputs.dir(kotlinTask.destinationDir)","I think you should also include kapt1 annotations file: +https://github.com/JetBrains/kotlin/blob/master/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AnnotationProcessingManager.kt#L139 + +In kapt1 AP is performed by java task, so if this file is not included, AP may be skipped when only source annotations are modified. +Kapt3 should probably work as intended. +I think the test should be added for this case (Java IC + Kapt 1/3 + change only Kotlin source annotations).",2017-03-14 09:54:19 +500,"@@ -56,11 +60,37 @@ fun generateIsCheck( + } + } + else { +- generateInstanceOfInstruction(v) ++ TypeIntrinsics.instanceOf(v, kotlinType, asmType) ++ } ++} ++ ++fun generateAsCheck(","`is` is a ""check"", but `as` is not :) `generateCast`? +",2015-12-28 15:07:05 +952,"@@ -56,6 +57,13 @@ open class AddModifierFix( + + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + element?.addModifier(modifier) ++ ++ if (modifier == KtTokens.ABSTRACT_KEYWORD && (element is KtProperty || element is KtNamedFunction)) { ++ element?.containingClass()?.run { ++ if (!hasModifier(KtTokens.ABSTRACT_KEYWORD) && !hasModifier(KtTokens.SEALED_KEYWORD)) addModifier(KtTokens.ABSTRACT_KEYWORD) ++ if (hasModifier(KtTokens.OPEN_KEYWORD)) removeModifier(KtTokens.OPEN_KEYWORD)","Should work without this line, at least in theory. Will check it myself.",2017-08-04 18:26:05 +535,"@@ -57,11 +58,10 @@ class KotlinMavenArchetypesProvider : MavenArchetypesProvider { + .asJsonArray + .map { it.asJsonObject } + .map { MavenArchetype(it.get(""g"").asString, it.get(""a"").asString, it.get(""v"").asString, null, null) } +- .filter { it.version.matches(versionRegexp) } +- .groupBy { it.artifactId + ""-"" + it.version.substringBeforeLast('.') } +- .mapValues { it.value.maxBy { a -> a.version.substringAfterLast('.').toInt() }!! } +- .values +- .toList() ++ .filter { it.version?.startsWith(versionPrefix) ?: false } ++ .maxBy { MavenVersionComparable(it.version) } ++ ?.let { listOf(it) }","It might be cleaner to use `listOfNotNull` instead of `?.let { listOf } ?: emptyList()` +",2016-03-31 15:16:06 +873,"@@ -57,6 +58,16 @@ class RedundantSemicolonInspection : AbstractKotlinInspection(), CleanupLocalIns + + if (semicolon.parent is KtEnumEntry) return false + ++ (semicolon.parent.parent as? KtClass)?.let { ++ if (it.isEnum() && it.getChildrenOfType().isEmpty()) { ++ if (semicolon.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment && !it.isLineBreak() }?.node?.elementType == KtTokens.LBRACE && ++ semicolon.nextLeaf { it !is PsiWhiteSpace && it !is PsiComment && !it.isLineBreak() }?.node?.elementType != KtTokens.RBRACE) {","I thinks it's more precise just to check here that `getDeclarations()` isn't empty, instead of doing these operations with `nextLeaf`.",2017-06-26 09:32:09 +309,"@@ -58,12 +68,22 @@ public fun CharSequence.iterator(): CharIterator = object : CharIterator() { + public override fun hasNext(): Boolean = index < length + } + +-/** Returns the string if it is not null or the empty string if its null */ ++/** Returns the string if it is not null, or the empty string otherwise. */ + public fun String?.orEmpty(): String = this ?: """" + ++/** ++ * Returns the range of valid character indices for this string. ++ */ + public val String.indices: IntRange + get() = 0..length() - 1 + ++/** ++ * Returns a character at the given index in a [CharSequence]. Allows to use the ++ * brackets notation for working with character sequences:","""brackets notation"" -> ""index operator"" +",2015-02-09 16:18:51 +650,"@@ -59,17 +90,49 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention()) return false ++ val bodyExpression = lambdaExpression.bodyExpression?.children?.singleOrNull() ?: return false ++ ++ return when (bodyExpression) { ++ is KtBinaryExpression -> bodyExpression.isApplication(parameterName) ++ is KtDotQualifiedExpression -> bodyExpression.isApplicable(parameterName)","Why is the first `isApplication`, but the second `isApplicable`? +",2016-11-07 09:26:04 +651,"@@ -59,17 +90,49 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention()) return false ++ val bodyExpression = lambdaExpression.bodyExpression?.children?.singleOrNull() ?: return false ++ ++ return when (bodyExpression) { ++ is KtBinaryExpression -> bodyExpression.isApplication(parameterName) ++ is KtDotQualifiedExpression -> bodyExpression.isApplicable(parameterName) ++ else -> false + } +- return !dotQualifiedExpression.receiverUsedAsArgument(parameterName) + } + ++ private fun KtBinaryExpression.isApplication(parameterName: String): Boolean { ++ val left = left ?: return false ++ ++ if (when (left) { ++ is KtNameReferenceExpression -> left.text != parameterName ++ is KtDotQualifiedExpression -> !left.isApplicable(parameterName) ++ else -> return false ++ }) return false","This construction is hard to read. I'd rewrite it like + +``` +when (...) { + is ... -> if (...) return false +} +``` +",2016-11-07 09:27:24 +866,"@@ -596,6 +596,12 @@ public void testSpaceBeforeFunctionLiteral() throws Exception { + doTest(fileName); + } + ++ @TestMetadata(""SpaceBeforeIndices.after.kt"") ++ public void testSpaceBeforeIndices() throws Exception { ++ String fileName = KotlinTestUtils.navigationMetadata(""idea/testData/formatter/SpaceBeforeIndices.after.kt""); ++ doTest(fileName); ++ } ++ + @TestMetadata(""SpacedInsideParans.after.kt"")",Lenor ,2017-05-31 19:47:02 +308,"@@ -6,7 +6,10 @@ public fun String.trim(text: String): String = trimLeading(text).trimTrailing(te + /** Returns the string with the prefix and postfix text trimmed */ + public fun String.trim(prefix: String, postfix: String): String = trimLeading(prefix).trimTrailing(postfix) + +-/** Returns the string with the leading prefix of this string removed */ ++/** ++ * If this string starts with the given [prefix], returns a copy of this string","Documentation is backwards. Normally it reads ""Returns a … if …, otherwise …"" +",2015-02-09 16:16:54 +1,"@@ -60,6 +60,8 @@ public inline fun String.format(format : String, vararg args : Any?) : String = + + public inline fun String.split(regex : String) : Array = (this as java.lang.String).split(regex) as Array + ++public inline fun String.split(ch : Char) : Array = (this as java.lang.String).split(java.util.regex.Pattern.quote(ch.toString())) as Array","Why here you are casting ""this"" to String? +",2012-04-23 06:52:06 +389,"@@ -61,6 +64,8 @@ protected void applyEditorTo(JetRunConfiguration configuration) throws Configura + myModuleSelector.applyTo(configuration); + myCommonProgramParameters.applyTo(configuration); + configuration.setRunClass(myMainClassField.getText()); ++ configuration.setAlternativeJrePath(alternativeJREPanel.getPath()); ++ configuration.setAlternativeJrePathEnabled(alternativeJREPanel.isPathEnabled());","Has it real effect during run? Is it enough to just set it to a configuration? +",2015-06-23 13:19:02 +611,"@@ -61,6 +66,13 @@ class KotlinIndicesHelper( + + private val moduleDescriptor = resolutionFacade.moduleDescriptor + private val project = resolutionFacade.project ++ private val scopeWithoutKotlin = ScopeWithoutKotlin(scope)","You can use `SearchUtil.excludeKotlinSources` +",2016-09-21 16:20:25 +242,"@@ -614,10 +614,22 @@ public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull O + } + + @NotNull ++ public static String getDefaultDescriptor(@NotNull String descriptor) {","Take a look on the usages, this method should take a `Method` as a parameter rather than a `String` +",2014-08-20 07:22:45 +240,"@@ -614,10 +614,22 @@ public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull O + } + + @NotNull ++ public static String getDefaultDescriptor(@NotNull String descriptor) { ++ // read Type.getArgumentsAndReturnSizes documentation for explanations","This comment is useless :) If I don't understand `>> 2`, I'll go and read what the method returns by myself, and if I do, I need not this comment at all +",2014-08-20 07:14:50 +239,"@@ -614,10 +614,22 @@ public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull O + } + + @NotNull ++ public static String getDefaultDescriptor(@NotNull String descriptor) { ++ // read Type.getArgumentsAndReturnSizes documentation for explanations ++ int argumentsSize = (Type.getArgumentsAndReturnSizes(descriptor) >> 2) - 1; ++ int maskArgumentsCont = argumentsSize / Integer.SIZE + (argumentsSize % Integer.SIZE == 0 ? 0 : 1);","Typo? _count_, not cont +",2014-08-20 07:10:01 +238,"@@ -614,10 +614,22 @@ public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull O + } + + @NotNull ++ public static String getDefaultDescriptor(@NotNull String descriptor) { ++ // read Type.getArgumentsAndReturnSizes documentation for explanations ++ int argumentsSize = (Type.getArgumentsAndReturnSizes(descriptor) >> 2) - 1; ++ int maskArgumentsCont = argumentsSize / Integer.SIZE + (argumentsSize % Integer.SIZE == 0 ? 0 : 1); ++ String maskArguments = ""I""; ++ for (int i = 1; i < maskArgumentsCont; i++) { ++ maskArguments += 'I'; ++ }","`StringUtil.repeat(INT_TYPE.getDescriptor(), maskArgumentsCount)` +",2014-08-20 07:09:14 +386,"@@ -63,12 +66,36 @@ private KotlinRuntimeLibraryUtil() {} + + @NotNull + public static Collection getLibraryRootsWithAbiIncompatibleKotlinClasses(@NotNull Project project) { +- return getLibraryRootsWithAbiIncompatibleVersion(project, KotlinAbiVersionIndex.INSTANCE$); ++ return getLibraryRootsWithAbiIncompatibleVersion(project, KotlinAbiVersionIndex.INSTANCE$, ++ new Predicate() { ++ @Override ++ public boolean apply(@Nullable Module module) { ++ return module != null && ProjectStructureUtil.isJavaKotlinModule(module); ++ } ++ }, ++ new Predicate() { ++ @Override ++ public boolean apply(Integer abiVersion) { ++ return !AbiVersionUtil.isAbiVersionCompatible(abiVersion); ++ } ++ });","Something wrong with formatting in this file I suppose? +",2015-06-11 21:59:37 +17,"@@ -63,3 +63,16 @@ public inline fun String.count(predicate: (Char) -> Boolean): Int { + } + return answer + } ++ ++/** ++ * Repeats a given string n times. With n <= 0, the empty string is returned.","I think it's better to throw IllegalArgumentException if n < 0, because it doesn't make much sense to hide user's error and return empty string in this case. +",2012-11-15 09:52:35 +16,"@@ -63,3 +63,16 @@ public inline fun String.count(predicate: (Char) -> Boolean): Int { + } + return answer + } ++ ++/** ++ * Repeats a given string n times. With n <= 0, the empty string is returned. ++ * @includeFunctionBody ../../test/StringTest.kt times ++ */ ++public inline fun String.times(var n: Int) : String { ++ var answer = """";","semicolons are noise which is unnecessary in Kotlin :) +",2012-11-15 09:48:58 +15,"@@ -63,3 +63,16 @@ public inline fun String.count(predicate: (Char) -> Boolean): Int { + } + return answer + } ++ ++/** ++ * Repeats a given string n times. With n <= 0, the empty string is returned. ++ * @includeFunctionBody ../../test/StringTest.kt times ++ */ ++public inline fun String.times(var n: Int) : String { ++ var answer = """"; ++ while (n > 0) { ++ answer = answer.concat(this)","I think that it'll be good to use StringBuilder#append instead of strings concatenations. +",2012-11-15 09:45:38 +892,"@@ -63,6 +63,13 @@ val PsiElement.parentsWithSelf: Sequence + val PsiElement.parents: Sequence + get() = parentsWithSelf.drop(1) + ++fun PsiElement.matchParents(vararg parentClasses: Class): Boolean { ++ return this.parents.zip(sequenceOf(*parentClasses)).all { ++ val (elem, clazz) = it ++ clazz.isAssignableFrom(elem.javaClass)","With lambda argument destructuring and `isInstance` method you could write this method as + +``` + return this.parents.zip(sequenceOf(*parentClasses)).all { (elem, clazz) -> + clazz.isInstance(elem) + } +```",2017-07-12 10:26:50 +690,"@@ -63,6 +63,7 @@ + + + ++ ",I'm not sure `javac` is the best possible name here. May be something like `javac-wrapper`?,2017-04-05 11:20:29 +493,"@@ -63,6 +65,10 @@ public abstract class KotlinLightCodeInsightFixtureTestCase : LightCodeInsightFi + super.processError(message, t, details, logger) + } + }) ++ ++ // set to false if not present or set to true or unknown (empty considered true) ++ if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY)?.let { it.toBooleanLenient() ?: true } ?: true )","This could be written as + +``` +if (KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.systemPropertyAsBooleanOrTrueOtherwise(negate = false)) { +``` +",2015-11-27 18:22:54 +976,"@@ -64,4 +66,92 @@ internal annotation class InlineOnly + */ + @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) + @Retention(AnnotationRetention.BINARY) +-internal annotation class DynamicExtension +\ No newline at end of file ++internal annotation class DynamicExtension ++ ++/** ++ * Specifies effect: annotated function returns specific value when condition provided ++ * by other annotations is true.* ++ */ ++@Target(AnnotationTarget.FUNCTION) ++@Retention(AnnotationRetention.BINARY) ++internal annotation class Returns(val value: ConstantValue = ConstantValue.UNKNOWN) ++ ++/** ++ * Specifies effect: annotated function throws 'exception' when condition is true ++ */ ++@Target(AnnotationTarget.FUNCTION) ++@Retention(AnnotationRetention.BINARY) ++internal annotation class Throws",I didn't notice any use of this annotation (may be I missed something),2017-08-15 16:17:28 +236,"@@ -64,6 +64,13 @@ + KotlinBuiltIns.getInstance().getChar() + ); + ++ private static final Set STRINGBULDER_OBJECT_APPEND_ARG_TYPES = Sets.newHashSet(","I think declaring a `Set` would be more straightforward. You can use `Type.getType(Class)` to create corresponding `Type` objects +",2014-05-12 20:45:35 +665,"@@ -650,7 +650,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter { + result = MethodCallExpression.buildNonNull(operandConverted, typeConversion) + } + else { +- val nullability = if (operandConverted.isNullable && !expression.isQualifier()) ++ val nullability = if ((operandConverted.isNullable && !expression.isQualifier()) || operandType == PsiType.NULL)","Better not to hack this check, but fix problem with `operandConverted.isNullable == false` for `null` literal ",2016-12-27 11:47:32 +586,"@@ -67,7 +73,15 @@ abstract class KtCodeFragment( + + override fun isValid() = true + +- override fun getContext() = context ++ override fun getContext(): PsiElement? { ++ if (fakeContextForJavaFile != null) return fakeContextForJavaFile ++ if (context !is KtElement) { ++ LOG.warn(""CodeFragment with non-kotlin context should have fakeContextForJavaFile set: \noriginalContext = ${context?.getElementTextWithContext()}"")","We shouldn't create kotlin codeFragments for scala files. See KotlinCodeFragmentFactory.isContextAccepted +",2016-08-03 14:06:55 +2,"@@ -68,10 +70,14 @@ public inline fun String.startsWith(prefix: String) : Boolean = (this as java.la + + public inline fun String.startsWith(prefix: String, toffset: Int) : Boolean = (this as java.lang.String).startsWith(prefix, toffset) + ++public inline fun String.startsWith(ch: Char) : Boolean = (this as java.lang.String).startsWith(ch.toString())","The same +",2012-04-23 06:52:41 +906,"@@ -68,3 +64,9 @@ class ClassBody( + builder.append(companionObjectMembers, ""\n"", ""companion object {\n"", ""\n}"") + } + } ++ ++private object PropertyComparator : Comparator { ++ override fun compare(o1: Member?, o2: Member?): Int { ++ return if (o1 is Property) if (o2 is Property) 0 else -1 else if (o2 is Property) 1 else 0",I'd use when for readability ,2017-07-17 18:14:59 +960,"@@ -69,6 +68,15 @@ class KotlinRedundantOverrideInspection : AbstractKotlinInspection(), CleanupLoc + } + } + ++ private fun KtNamedFunction.containsOtherModifier(): Boolean { ++ MODIFIER_EXCLUDE_OVERRIDE.forEach {",You can simplify this to `return MODIFIER_EXCLUDE_OVERRIDE.any { hasModifier(it) }`,2017-08-15 09:48:07 +19,"@@ -69,7 +72,18 @@ public TextRange getRangeInElement() { + + @Override + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { +- PsiElement element = JetPsiFactory.createNameIdentifier(myExpression.getProject(), newElementName); ++ IElementType type = myExpression.getReferencedNameElementType(); ++ final PsiElement element;","We do not mark variables final unless this is required by the compiler. +",2013-01-11 15:18:39 +420,"@@ -69,7 +78,7 @@ public static void runK2JsCompiler( + @NotNull CompilerSettings compilerSettings, + @NotNull MessageCollector messageCollector, + @NotNull CompilerEnvironment environment, +- @NotNull OutputItemsCollector collector, ++ Map incrementalCaches, @NotNull OutputItemsCollector collector,","Same here --- one parameter per line. +",2015-08-20 14:11:23 +344,"@@ -7,127 +7,358 @@ import java.util.regex.MatchResult + import java.util.regex.Pattern + import java.nio.charset.Charset + ++/** ++ * Returns the index within this string of the last occurrence of the specified substring. ++ */ + public fun String.lastIndexOf(str: String): Int = (this as java.lang.String).lastIndexOf(str) + ++/** ++ * Returns the index within this string of the last occurrence of the specified character. ++ */ + public fun String.lastIndexOf(ch: Char): Int = (this as java.lang.String).lastIndexOf(ch.toString()) + ++/** ++ * Compares this string to another string, ignoring case considerations. ++ */ + public fun String.equalsIgnoreCase(anotherString: String): Boolean = (this as java.lang.String).equalsIgnoreCase(anotherString) + ++/** ++ * Returns the hash code of this string. ++ */ + public fun String.hashCode(): Int = (this as java.lang.String).hashCode() + ++/** ++ * Returns the index within this string of the first occurrence of the specified substring. ++ */ + public fun String.indexOf(str: String): Int = (this as java.lang.String).indexOf(str) + ++/** ++ * Returns the index within this string of the first occurrence of the specified substring, starting from the specified offset. ++ */ + public fun String.indexOf(str: String, fromIndex: Int): Int = (this as java.lang.String).indexOf(str, fromIndex) + ++/** ++ * Returns a copy of this string with all occurrences of [oldChar] replaced with [newChar]. ++ */ + public fun String.replace(oldChar: Char, newChar: Char): String = (this as java.lang.String).replace(oldChar, newChar) + ++/** ++ * Returns a new string obtained by replacing each substring of this string that matches the given regular expression ++ * with the given [replacement]. ++ */ + public fun String.replaceAll(regex: String, replacement: String): String = (this as java.lang.String).replaceAll(regex, replacement) + ++/** ++ * Returns a copy of this string with leading and trailing whitespace trimmed. ++ */ + public fun String.trim(): String = (this as java.lang.String).trim() + ++/** ++ * Returns a copy of this string converted to upper case using the rules of the default locale. ++ */ + public fun String.toUpperCase(): String = (this as java.lang.String).toUpperCase() + ++/** ++ * Returns a copy of this string converted to lower case using the rules of the default locale. ++ */ + public fun String.toLowerCase(): String = (this as java.lang.String).toLowerCase() + ++/** ++ * Returns a new character array containing the characters from this string. ++ */ + public fun String.toCharArray(): CharArray = (this as java.lang.String).toCharArray() + ++/** ++ * Uses this string as a format string and returns a string obtained by substituting the specified arguments, ++ * using the default locale. ++ */ + public fun String.format(vararg args: Any?): String = java.lang.String.format(this, *args) + ++/** ++ * Uses this string as a format string and returns a string obtained by substituting the specified arguments, using ++ * the specified locale. ++ */ + public fun String.format(locale: Locale, vararg args : Any?) : String = java.lang.String.format(locale, this, *args) + ++/** ++ * Splits this string around matches of the given regular expression. ++ */ + public fun String.split(regex: String): Array = (this as java.lang.String).split(regex) + ++/** ++ * Splits this string around occurrences of the specified character. ++ */ + public fun String.split(ch: Char): Array = (this as java.lang.String).split(java.util.regex.Pattern.quote(ch.toString())) + ++/** ++ * Returns a substring of this string starting with the specified index. ++ */ + public fun String.substring(beginIndex: Int): String = (this as java.lang.String).substring(beginIndex) + ++/** ++ * Returns the substring of this string starting and ending at the specified indices. ++ */ + public fun String.substring(beginIndex: Int, endIndex: Int): String = (this as java.lang.String).substring(beginIndex, endIndex) + ++/** ++ * Returns `true` if this string starts with the specified prefix. ++ */ + public fun String.startsWith(prefix: String): Boolean = (this as java.lang.String).startsWith(prefix) + ++/** ++ * Returns `true` if a subsring of this string starting at the specified offset starts with the specified prefix. ++ */ + public fun String.startsWith(prefix: String, toffset: Int): Boolean = (this as java.lang.String).startsWith(prefix, toffset) + ++/** ++ * Returns `true` if this string starts with the specified character. ++ */ + public fun String.startsWith(ch: Char): Boolean = (this as java.lang.String).startsWith(ch.toString()) + ++/** ++ * Returns `true` if this string contains the specified sequence of characters as a substring. ++ */ + public fun String.contains(seq: CharSequence): Boolean = (this as java.lang.String).contains(seq) + ++/** ++ * Returns `true` if this string ends with the specified suffix. ++ */ + public fun String.endsWith(suffix: String): Boolean = (this as java.lang.String).endsWith(suffix) + ++/** ++ * Returns `true` if this string ends with the specified character. ++ */ + public fun String.endsWith(ch: Char): Boolean = (this as java.lang.String).endsWith(ch.toString()) + + // ""constructors"" for String + ++/** ++ * Converts the data from a portion of the specified array of bytes to characters using the specified character set ++ * and returns the conversion result as a string. ++ * ++ * @param offset the offset in the array of the data to be converted. ++ * @param length the number of bytes to be converted.","charsetName parameter missing +",2015-03-12 15:05:31 +345,"@@ -7,127 +7,358 @@ import java.util.regex.MatchResult + import java.util.regex.Pattern + import java.nio.charset.Charset + ++/** ++ * Returns the index within this string of the last occurrence of the specified substring. ++ */ + public fun String.lastIndexOf(str: String): Int = (this as java.lang.String).lastIndexOf(str) + ++/** ++ * Returns the index within this string of the last occurrence of the specified character. ++ */ + public fun String.lastIndexOf(ch: Char): Int = (this as java.lang.String).lastIndexOf(ch.toString()) + ++/** ++ * Compares this string to another string, ignoring case considerations. ++ */ + public fun String.equalsIgnoreCase(anotherString: String): Boolean = (this as java.lang.String).equalsIgnoreCase(anotherString) + ++/** ++ * Returns the hash code of this string. ++ */ + public fun String.hashCode(): Int = (this as java.lang.String).hashCode() + ++/** ++ * Returns the index within this string of the first occurrence of the specified substring. ++ */ + public fun String.indexOf(str: String): Int = (this as java.lang.String).indexOf(str) + ++/** ++ * Returns the index within this string of the first occurrence of the specified substring, starting from the specified offset. ++ */ + public fun String.indexOf(str: String, fromIndex: Int): Int = (this as java.lang.String).indexOf(str, fromIndex) + ++/** ++ * Returns a copy of this string with all occurrences of [oldChar] replaced with [newChar]. ++ */ + public fun String.replace(oldChar: Char, newChar: Char): String = (this as java.lang.String).replace(oldChar, newChar) + ++/** ++ * Returns a new string obtained by replacing each substring of this string that matches the given regular expression ++ * with the given [replacement]. ++ */ + public fun String.replaceAll(regex: String, replacement: String): String = (this as java.lang.String).replaceAll(regex, replacement) + ++/** ++ * Returns a copy of this string with leading and trailing whitespace trimmed. ++ */ + public fun String.trim(): String = (this as java.lang.String).trim() + ++/** ++ * Returns a copy of this string converted to upper case using the rules of the default locale. ++ */ + public fun String.toUpperCase(): String = (this as java.lang.String).toUpperCase() + ++/** ++ * Returns a copy of this string converted to lower case using the rules of the default locale. ++ */ + public fun String.toLowerCase(): String = (this as java.lang.String).toLowerCase() + ++/** ++ * Returns a new character array containing the characters from this string. ++ */ + public fun String.toCharArray(): CharArray = (this as java.lang.String).toCharArray() + ++/** ++ * Uses this string as a format string and returns a string obtained by substituting the specified arguments, ++ * using the default locale. ++ */ + public fun String.format(vararg args: Any?): String = java.lang.String.format(this, *args) + ++/** ++ * Uses this string as a format string and returns a string obtained by substituting the specified arguments, using ++ * the specified locale. ++ */ + public fun String.format(locale: Locale, vararg args : Any?) : String = java.lang.String.format(locale, this, *args) + ++/** ++ * Splits this string around matches of the given regular expression. ++ */ + public fun String.split(regex: String): Array = (this as java.lang.String).split(regex) + ++/** ++ * Splits this string around occurrences of the specified character. ++ */ + public fun String.split(ch: Char): Array = (this as java.lang.String).split(java.util.regex.Pattern.quote(ch.toString())) + ++/** ++ * Returns a substring of this string starting with the specified index. ++ */ + public fun String.substring(beginIndex: Int): String = (this as java.lang.String).substring(beginIndex) + ++/** ++ * Returns the substring of this string starting and ending at the specified indices. ++ */ + public fun String.substring(beginIndex: Int, endIndex: Int): String = (this as java.lang.String).substring(beginIndex, endIndex) + ++/** ++ * Returns `true` if this string starts with the specified prefix. ++ */ + public fun String.startsWith(prefix: String): Boolean = (this as java.lang.String).startsWith(prefix) + ++/** ++ * Returns `true` if a subsring of this string starting at the specified offset starts with the specified prefix. ++ */ + public fun String.startsWith(prefix: String, toffset: Int): Boolean = (this as java.lang.String).startsWith(prefix, toffset) + ++/** ++ * Returns `true` if this string starts with the specified character. ++ */ + public fun String.startsWith(ch: Char): Boolean = (this as java.lang.String).startsWith(ch.toString()) + ++/** ++ * Returns `true` if this string contains the specified sequence of characters as a substring. ++ */ + public fun String.contains(seq: CharSequence): Boolean = (this as java.lang.String).contains(seq) + ++/** ++ * Returns `true` if this string ends with the specified suffix. ++ */ + public fun String.endsWith(suffix: String): Boolean = (this as java.lang.String).endsWith(suffix) + ++/** ++ * Returns `true` if this string ends with the specified character. ++ */ + public fun String.endsWith(ch: Char): Boolean = (this as java.lang.String).endsWith(ch.toString()) + + // ""constructors"" for String + ++/** ++ * Converts the data from a portion of the specified array of bytes to characters using the specified character set ++ * and returns the conversion result as a string. ++ * ++ * @param offset the offset in the array of the data to be converted. ++ * @param length the number of bytes to be converted. ++ */ + public fun String(bytes: ByteArray, offset: Int, length: Int, charsetName: String): String = java.lang.String(bytes, offset, length, charsetName) as String + ++/** ++ * Converts the data from a portion of the specified array of bytes to characters using the specified character set ++ * and returns the conversion result as a string. ++ * ++ * @param offset the offset in the array of the data to be converted. ++ * @param length the number of bytes to be converted. ++ */","charset parameter missing +",2015-03-12 15:05:45 +937,"@@ -70,7 +72,11 @@ fun KtLambdaArgument.moveInsideParenthesesAndReplaceWith( + val newCallExpression = oldCallExpression.copy() as KtCallExpression + + val psiFactory = KtPsiFactory(project) +- val argument = if (newCallExpression.getValueArgumentsInParentheses().any { it.isNamed() }) { ++ ++ val argument = if (newCallExpression.getValueArgumentsInParentheses().run {",I think this nested `run` expression is far too complex. Better to extract this logic into a method.,2017-08-03 09:53:52 +250,"@@ -71,48 +90,72 @@ public open class KotlinCompile(): AbstractCompile() { + + [TaskAction] + override fun compile() { +- +- getLogger().debug(""Starting Kotlin compilation task"") +- +- val args = K2JVMCompilerArguments() +- +- val javaSrcRoots = HashSet() +- val sources = ArrayList() +- +- // collect source directory roots for all java files to allow cross compilation +- for (file in getSource()) { +- if (FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(""java"")) { +- val javaRoot = findSrcDirRoot(file) +- if (javaRoot != null) { +- javaSrcRoots.add(javaRoot) +- } +- } else { +- sources.add(file) +- } +- } +- ++ getLogger().debug(""Starting ${javaClass} task"") ++ val args = createBlankArgs() ++ val sources = getKotlinSources() + if (sources.empty) { + getLogger().warn(""No Kotlin files found, skipping Kotlin compiler task"") + return + } + ++ populateTargetSpecificArgs(args, sources) ++ populateCommonArgs(args, sources) ++ callCompiler(args) ++ afterCompileHook(args) ++ } ++ ++ protected fun isJava(it: File): Boolean = FilenameUtils.getExtension(it.getName()).equalsIgnoreCase(""java"") ++ ++ private fun getKotlinSources(): ArrayList = getSource()","The call chain may be written in one line +",2014-11-11 17:14:33 +253,"@@ -71,48 +90,72 @@ public open class KotlinCompile(): AbstractCompile() { + + [TaskAction] + override fun compile() { +- +- getLogger().debug(""Starting Kotlin compilation task"") +- +- val args = K2JVMCompilerArguments() +- +- val javaSrcRoots = HashSet() +- val sources = ArrayList() +- +- // collect source directory roots for all java files to allow cross compilation +- for (file in getSource()) { +- if (FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(""java"")) { +- val javaRoot = findSrcDirRoot(file) +- if (javaRoot != null) { +- javaSrcRoots.add(javaRoot) +- } +- } else { +- sources.add(file) +- } +- } +- ++ getLogger().debug(""Starting ${javaClass} task"") ++ val args = createBlankArgs() ++ val sources = getKotlinSources() + if (sources.empty) { + getLogger().warn(""No Kotlin files found, skipping Kotlin compiler task"") + return + } + ++ populateTargetSpecificArgs(args, sources) ++ populateCommonArgs(args, sources) ++ callCompiler(args) ++ afterCompileHook(args) ++ } ++ ++ protected fun isJava(it: File): Boolean = FilenameUtils.getExtension(it.getName()).equalsIgnoreCase(""java"") ++ ++ private fun getKotlinSources(): ArrayList = getSource() ++ .filterNot { isJava(it) }","I think more properly to check that it's kotlin file. + +P.S. I see that it's legacy code +",2014-11-11 17:59:07 +252,"@@ -71,48 +90,72 @@ public open class KotlinCompile(): AbstractCompile() { + + [TaskAction] + override fun compile() { +- +- getLogger().debug(""Starting Kotlin compilation task"") +- +- val args = K2JVMCompilerArguments() +- +- val javaSrcRoots = HashSet() +- val sources = ArrayList() +- +- // collect source directory roots for all java files to allow cross compilation +- for (file in getSource()) { +- if (FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(""java"")) { +- val javaRoot = findSrcDirRoot(file) +- if (javaRoot != null) { +- javaSrcRoots.add(javaRoot) +- } +- } else { +- sources.add(file) +- } +- } +- ++ getLogger().debug(""Starting ${javaClass} task"") ++ val args = createBlankArgs() ++ val sources = getKotlinSources() + if (sources.empty) { + getLogger().warn(""No Kotlin files found, skipping Kotlin compiler task"") + return + } + ++ populateTargetSpecificArgs(args, sources) ++ populateCommonArgs(args, sources) ++ callCompiler(args) ++ afterCompileHook(args) ++ } ++ ++ protected fun isJava(it: File): Boolean = FilenameUtils.getExtension(it.getName()).equalsIgnoreCase(""java"") ++ ++ private fun getKotlinSources(): ArrayList = getSource() ++ .filterNot { isJava(it) } ++ .toArrayList() ++ ++ protected fun populateCommonArgs(args: T, sources: ArrayList) {","should be it private? +",2014-11-11 17:48:45 +251,"@@ -71,48 +90,72 @@ public open class KotlinCompile(): AbstractCompile() { + + [TaskAction] + override fun compile() { +- +- getLogger().debug(""Starting Kotlin compilation task"") +- +- val args = K2JVMCompilerArguments() +- +- val javaSrcRoots = HashSet() +- val sources = ArrayList() +- +- // collect source directory roots for all java files to allow cross compilation +- for (file in getSource()) { +- if (FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(""java"")) { +- val javaRoot = findSrcDirRoot(file) +- if (javaRoot != null) { +- javaSrcRoots.add(javaRoot) +- } +- } else { +- sources.add(file) +- } +- } +- ++ getLogger().debug(""Starting ${javaClass} task"") ++ val args = createBlankArgs() ++ val sources = getKotlinSources() + if (sources.empty) { + getLogger().warn(""No Kotlin files found, skipping Kotlin compiler task"") + return + } + ++ populateTargetSpecificArgs(args, sources) ++ populateCommonArgs(args, sources) ++ callCompiler(args) ++ afterCompileHook(args) ++ } ++ ++ protected fun isJava(it: File): Boolean = FilenameUtils.getExtension(it.getName()).equalsIgnoreCase(""java"") ++ ++ private fun getKotlinSources(): ArrayList = getSource() ++ .filterNot { isJava(it) } ++ .toArrayList() ++ ++ protected fun populateCommonArgs(args: T, sources: ArrayList) { ++ args.freeArgs = sources.map { it.getAbsolutePath() } + args.suppressWarnings = kotlinOptions.suppressWarnings ++ args.verbose = kotlinOptions.verbose + args.version = kotlinOptions.version +- args.verbose = logger.isDebugEnabled() ++ args.noInline = kotlinOptions.noInline ++ } + +- args.freeArgs = sources.map { it.getAbsolutePath() } ++ abstract protected fun populateTargetSpecificArgs(args: T, sources: ArrayList)","looks like we don't need `sources` in `populateTargetSpecificArgs` +",2014-11-11 17:41:41 +559,"@@ -714,6 +714,43 @@ class StringTest { + } + } + ++ @test fun occurencesOf() { ++ // Multiple overlapping occurances ++ assertEquals(""abaabaaababac"".occurrencesOf(""abaa"", matchOverlapping = true).toList(), listOf(0, 3))","`expected` value comes first, `actual` value second. +",2016-05-17 19:17:46 +994,"@@ -73,10 +73,10 @@ object SwitchDemo { + val status = """" + when (status) { + ""init"", ""dial"", ""transmit"" -> return 0x111111 +- ""ok"" -> return 0xFF006600.toInt() +- ""cancel"" -> return 0xFF666666.toInt() +- ""fail"", ""busy"", ""error"" -> return 0xFF660000.toInt() +- else -> return 0xFF660000.toInt() ++ ""ok"" -> return -16751104","Please, write out these numbers in hex, if input in hex. ",2017-08-16 12:34:22 +32,"@@ -73,6 +73,14 @@ public static ASTNode createColonNode(Project project) { + return property.getNode().findChildByType(JetTokens.COLON); + } + ++ @NotNull ++ public static PsiElement createSemicolon(Project project) { ++ JetProperty property = createProperty(project, ""val x: Int;""); ++ PsiElement colon = property.findElementAt(10);","Colon variable should be renamed to senilicon +",2013-02-21 14:22:36 +339,"@@ -75,6 +75,9 @@ public fun ByteArray.toString(charset: String): String = String(this, charset) + */ + public fun ByteArray.toString(charset: Charset): String = String(this, charset) + ++/** ++ * Returnsn an array containing the elements of this collection.","typo ""returnsn"" +",2015-03-12 14:54:06 +993,"@@ -77,13 +78,18 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() { + delegateBuilder.enterSubroutine(subroutine) + } + +- override fun exitSubroutine(subroutine: KtElement): Pseudocode { +- super.exitSubroutine(subroutine) ++ override fun exitSubroutine(subroutine: KtElement, invocationKind: InvocationKind?): Pseudocode { ++ super.exitSubroutine(subroutine, invocationKind) + delegateBuilder.exitBlockScope(subroutine) + val worker = popBuilder() + if (!builders.empty()) { + val builder = builders.peek() +- builder.declareFunction(subroutine, worker.pseudocode) ++ ++ if (invocationKind == null) { ++ builder.declareFunction(subroutine, worker.pseudocode) ++ } else {",Formatting,2017-08-16 09:43:12 +49,"@@ -77,6 +77,18 @@ private static void addName(ArrayList result, String name, JetNameValida + if (result.isEmpty()) addName(result, ""value"", validator); + return ArrayUtil.toStringArray(result); + } ++ ++ public static String[] suggestNamesForType(JetType jetType, JetNameValidator validator) { ++ ArrayList result = new ArrayList(); ++ addNamesForType(result, jetType, validator); ++ return ArrayUtil.toStringArray(result); ++ } ++ ++ public static String[] suggestNamesForExpression(JetExpression expression, JetNameValidator validator) { ++ ArrayList result = new ArrayList(); ++ addNamesForExpression(result, expression, validator); ++ return ArrayUtil.toStringArray(result);","Why converting this to array? Why not return list? +",2013-04-26 11:10:15 +291,"@@ -773,7 +773,7 @@ public fun Array.slice(indices: Iterable): List { + } + + /** +- * Returns a list containing elements at specified positions ++ * Returns a string containing characters at specified positions","copypasta: Array is not a string +",2015-02-09 15:52:41 +877,"@@ -78,7 +81,7 @@ private fun collectNullCheckExpressions(expression: KtBinaryExpression): Triple< + + private fun isNullChecksToSafeCallFixAvailable(expression: KtBinaryExpression): Boolean { + val (lte, rte) = collectNullCheckExpressions(expression) ?: return false +- return getDuplicates(lte, rte)?.parent as? KtDotQualifiedExpression != null ++ return lte.isChainStable() && getDuplicates(lte, rte)?.parent as? KtDotQualifiedExpression != null",At least one or two tests required here,2017-07-03 12:02:22 +379,"@@ -8,6 +8,7 @@ false + for + if + in ++interface","Why? +",2015-04-27 10:32:01 +463,"@@ -81,16 +81,11 @@ public abstract class AnnotationProcessorWrapper( + return + } + +- val annotationsFile = processingEnv.getOptions().get(KAPT_ANNOTATION_OPTION) +- if (annotationsFile != null) { +- try { +- kotlinAnnotationsProvider = FileKotlinAnnotationProvider(File(annotationsFile)) +- } +- catch (e: IOException) { +- kotlinAnnotationsProvider = EmptyKotlinAnnotationsProvider() +- } +- } +- else kotlinAnnotationsProvider = EmptyKotlinAnnotationsProvider() ++ val annotationsFilePath = processingEnv.getOptions().get(KAPT_ANNOTATION_OPTION) ++ val annotationsFile = if (annotationsFilePath != null) File(annotationsFilePath) else null ++ kotlinAnnotationsProvider = if (annotationsFile != null && annotationsFile.exists()) { ++ FileKotlinAnnotationProvider(annotationsFile) ++ } else EmptyKotlinAnnotationsProvider()","Could you please put `else` on the new line and add `{}` for it? So it would be agreed with our coding conventions. +",2015-08-31 12:51:52 +973,"@@ -82,7 +89,8 @@ public inline fun checkNotNull(value: T?): T = checkNotNull(value) { ""Re + * @sample samples.misc.Preconditions.failCheckWithLazyMessage + */ + @kotlin.internal.InlineOnly +-public inline fun checkNotNull(value: T?, lazyMessage: () -> Any): T { ++@kotlin.internal.Returns ++public inline fun checkNotNull(@kotlin.internal.Equals(kotlin.internal.ConstantValue.NOT_NULL) value: T?, lazyMessage: () -> Any): T {",Can we annotate also `error` below?,2017-08-15 16:08:34 +836,"@@ -824,6 +824,8 @@ + DiagnosticFactory0 ALWAYS_NULL = DiagnosticFactory0.create(WARNING); + + DiagnosticFactory0 USELESS_NULLABLE_CHECK = DiagnosticFactory0.create(WARNING, NULLABLE_TYPE); ++ DiagnosticFactory0 USELESS_IS_CHECK = DiagnosticFactory0.create(WARNING); ++ DiagnosticFactory0 USELESS_IS_NOT_CHECK = DiagnosticFactory0.create(WARNING);","I'd propose to use one diagnostiс: +``` +DiagnosticFactory1 USELESS_IS_CHECK = DiagnosticFactory1.create(WARNING); +```",2017-05-02 18:34:14 +643,"@@ -83,6 +83,35 @@ object MoveDeclarationsOutHelper { + return PsiUtilCore.toPsiElementArray(resultStatements) + } + ++ private fun addSymbolAfterDeclaration(container: PsiElement, declaration: KtProperty, isLastStatemnt: Boolean) {","typo: statemnt -> statement +",2016-10-18 18:48:22 +644,"@@ -83,6 +83,35 @@ object MoveDeclarationsOutHelper { + return PsiUtilCore.toPsiElementArray(resultStatements) + } + ++ private fun addSymbolAfterDeclaration(container: PsiElement, declaration: KtProperty, isLastStatemnt: Boolean) { ++ if (isLastStatemnt) { ++ container.addAfter(KtPsiFactory(declaration).createEQ(), declaration) ++ } ++ else { ++ container.addAfter(KtPsiFactory(declaration).createNewLine(), declaration)","It should never be necessary to create newlines from text. All newlines should be inserted by the formatter. +",2016-10-18 18:53:52 +871,"@@ -83,7 +84,9 @@ sealed class ReplCompileResult : Serializable { + val mainClassName: String, + val classes: List, + val hasResult: Boolean, +- val classpathAddendum: List) : ReplCompileResult() ++ val classpathAddendum: List) : ReplCompileResult() { ++ val type = LastInferredTypeHolder.inferredType.get()","It would be easier to pass the expression type explicitly to `ReplCompileResult.CompiledClasses`'s constructor where it's created at `GenericReplCompiler.compile` with: +``` +val expression = psiFile.getChildOfType() +compilerState.analyzerEngine.trace.bindingContext.getType(expression) +``` +(+ handle the case when there's no expression in a REPL line)",2017-06-13 14:33:56 +310,"@@ -84,109 +104,113 @@ public fun CharSequence.slice(indices: Iterable): CharSequence { + } + + /** +- * Returns a substring specified by given range ++ * Returns a substring specified by the given [range]. + */ + public fun String.substring(range: IntRange): String = substring(range.start, range.end + 1) + + /** +- * Creates a string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied. +- * If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will +- * a special *truncated* separator (which defaults to ""..."") ++ * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. ++ * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] ++ * elements will be appended, followed by the [truncated] string (which defaults to ""...""). + */ + public fun Iterable.join(separator: String = "", "", prefix: String = """", postfix: String = """", limit: Int = -1, truncated: String = ""...""): String { + return joinToString(separator, prefix, postfix, limit, truncated) + } + + /** +- * Creates a string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied. +- * If an array could be huge you can specify a non-negative value of *limit* which will only show a subset of the array then it will +- * a special *truncated* separator (which defaults to ""..."") ++ * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. ++ * If the array could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] ++ * elements will be appended, followed by the [truncated] string (which defaults to ""...""). + */ + public fun Array.join(separator: String = "", "", prefix: String = """", postfix: String = """", limit: Int = -1, truncated: String = ""...""): String { + return joinToString(separator, prefix, postfix, limit, truncated) + } + + /** +- * Creates a string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied. +- * If a stream could be huge you can specify a non-negative value of *limit* which will only show a subset of the stream then it will +- * a special *truncated* separator (which defaults to ""..."") ++ * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. ++ * If the stream could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] ++ * elements will be appended, followed by the [truncated] string (which defaults to ""...""). + */ + public fun Stream.join(separator: String = "", "", prefix: String = """", postfix: String = """", limit: Int = -1, truncated: String = ""...""): String { + return joinToString(separator, prefix, postfix, limit, truncated) + } ++ + /** +- * Returns a substring before first occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring before the first occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringBefore(delimiter: Char, missingSeparatorValue : String = this): String { ++public fun String.substringBefore(delimiter: Char, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(0, index) ++ return if (index == -1) missingDelimiterValue else substring(0, index) + } + + /** +- * Returns a substring before first occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring before the first occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringBefore(delimiter: String, missingSeparatorValue : String = this): String { ++public fun String.substringBefore(delimiter: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(0, index) ++ return if (index == -1) missingDelimiterValue else substring(0, index) + } ++ + /** +- * Returns a substring after first occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring after the first occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringAfter(delimiter: Char, missingSeparatorValue : String = this): String { ++public fun String.substringAfter(delimiter: Char, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(index + 1, length) ++ return if (index == -1) missingDelimiterValue else substring(index + 1, length) + } + + /** +- * Returns a substring after first occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring after the first occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringAfter(delimiter: String, missingSeparatorValue : String = this): String { ++public fun String.substringAfter(delimiter: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(index + delimiter.length, length) ++ return if (index == -1) missingDelimiterValue else substring(index + delimiter.length, length) + } + + /** +- * Returns a substring before last occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring before the last occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringBeforeLast(delimiter: Char, missingSeparatorValue : String = this): String { ++public fun String.substringBeforeLast(delimiter: Char, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(0, index) ++ return if (index == -1) missingDelimiterValue else substring(0, index) + } + + /** +- * Returns a substring before last occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring before the last occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringBeforeLast(delimiter: String, missingSeparatorValue : String = this): String { ++public fun String.substringBeforeLast(delimiter: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(0, index) ++ return if (index == -1) missingDelimiterValue else substring(0, index) + } + + /** +- * Returns a substring after last occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring after the last occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringAfterLast(delimiter: Char, missingSeparatorValue : String = this): String { ++public fun String.substringAfterLast(delimiter: Char, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(index + 1, length) ++ return if (index == -1) missingDelimiterValue else substring(index + 1, length) + } + + /** +- * Returns a substring after last occurrence of delimiter. +- * In case of no delimiter, returns the value of missingSeparatorValue which defaults to original string. ++ * Returns a substring after the last occurrence of [delimiter]. ++ * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +-public fun String.substringAfterLast(delimiter: String, missingSeparatorValue : String = this): String { ++public fun String.substringAfterLast(delimiter: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) +- return if (index == -1) missingSeparatorValue else substring(index + delimiter.length, length) ++ return if (index == -1) missingDelimiterValue else substring(index + delimiter.length, length) + } + + /** +- * Replace part of string at given range with replacement string ++ * Replace the part of string at given the range with the [replacement] string.","""Replaces"", ""of the string"" +",2015-02-09 16:20:50 +608,"@@ -85,30 +87,73 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() + dest.addAll(allClassNames) + } + +- override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array +- = emptyArray() ++ override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array { ++ return getMethodSequenceByName(name, scope).toList().toTypedArray() ++ } ++ ++ fun getMethodSequenceByName(name: String, scope: GlobalSearchScope): Sequence { ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val functionIndex = KotlinFunctionShortNameIndex.getInstance() ++ ++ val kotlinFunctionsPsi = functionIndex.get(name, project, scope).asSequence() ++ .flatMap { LightClassUtil.getLightClassMethods(it).asSequence() } ++ .filter { it.name == name } ++ ++ val propertyAccessorsPsi = getPropertyNamesCandidatesByAccessorName(Name.identifier(name)).asSequence() ++ .flatMap { propertiesIndex.get(it.asString(), project, scope).asSequence() } ++ .flatMap { LightClassUtil.getLightClassPropertyMethods(it).allDeclarations.asSequence() } ++ .filter { it.name == name } ++ .map { it as? PsiMethod } + +- override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array +- = emptyArray() ++ return (propertyAccessorsPsi + kotlinFunctionsPsi).filterNotNull()","This accesses the property index even if it's not actually necessary (if the sequence enumeration stops before we reach the property names). Would be nice to use something like `sequenceOfLazyValues().flatMap` to avoid this. +",2016-09-19 15:22:32 +609,"@@ -85,30 +87,73 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() + dest.addAll(allClassNames) + } + +- override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array +- = emptyArray() ++ override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array { ++ return getMethodSequenceByName(name, scope).toList().toTypedArray() ++ } ++ ++ fun getMethodSequenceByName(name: String, scope: GlobalSearchScope): Sequence { ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val functionIndex = KotlinFunctionShortNameIndex.getInstance() ++ ++ val kotlinFunctionsPsi = functionIndex.get(name, project, scope).asSequence() ++ .flatMap { LightClassUtil.getLightClassMethods(it).asSequence() } ++ .filter { it.name == name } ++ ++ val propertyAccessorsPsi = getPropertyNamesCandidatesByAccessorName(Name.identifier(name)).asSequence() ++ .flatMap { propertiesIndex.get(it.asString(), project, scope).asSequence() } ++ .flatMap { LightClassUtil.getLightClassPropertyMethods(it).allDeclarations.asSequence() } ++ .filter { it.name == name } ++ .map { it as? PsiMethod } + +- override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array +- = emptyArray() ++ return (propertyAccessorsPsi + kotlinFunctionsPsi).filterNotNull() ++ } ++ ++ override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array { ++ val psiMethods = getMethodSequenceByName(name, scope) ++ val limitedByMaxCount = psiMethods.take(maxCount) ++ psiMethods.drop(maxCount).firstOrNull()?.let { return PsiMethod.EMPTY_ARRAY }","You can avoid repeated iteration of the sequence if you use `take(maxCount+1)` and check if you actually got N+1 elements. +",2016-09-19 15:24:10 +600,"@@ -85,30 +87,78 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() + dest.addAll(allClassNames) + } + +- override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array +- = emptyArray() ++ override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array { ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val functionIndex = KotlinFunctionShortNameIndex.getInstance() + +- override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array +- = emptyArray() ++ val kotlinFunctionsPsi = functionIndex.get(name, project, scope) ++ .flatMap { LightClassUtil.getLightClassMethods(it) } + +- override fun getFieldsByNameIfNotMoreThan(s: String, scope: GlobalSearchScope, i: Int): Array +- = emptyArray() ++ val propertyAccessorsPsi = getPropertyNamesCandidatesByAccessorName(Name.identifier(name)) ++ .flatMap { propertiesIndex.get(it.asString(), project, scope) } ++ .flatMap { LightClassUtil.getLightClassPropertyMethods(it).allDeclarations } ++ .filter { it.name == name } ++ .map { it as? PsiMethod } ++ ++ return (propertyAccessorsPsi + kotlinFunctionsPsi).filterNotNull().toList().toTypedArray() ++ } ++ ++ override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array { ++ val methods = getMethodsByName(name, scope) ++ if (methods.size > maxCount)","This implementation defeats the purpose of this method. You should calculate the candidates lazily and stop evaluating if you've found more than `maxCount` candidates. +",2016-09-05 17:33:47 +601,"@@ -85,30 +87,78 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() + dest.addAll(allClassNames) + } + +- override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array +- = emptyArray() ++ override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array { ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val functionIndex = KotlinFunctionShortNameIndex.getInstance() + +- override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array +- = emptyArray() ++ val kotlinFunctionsPsi = functionIndex.get(name, project, scope) ++ .flatMap { LightClassUtil.getLightClassMethods(it) } + +- override fun getFieldsByNameIfNotMoreThan(s: String, scope: GlobalSearchScope, i: Int): Array +- = emptyArray() ++ val propertyAccessorsPsi = getPropertyNamesCandidatesByAccessorName(Name.identifier(name)) ++ .flatMap { propertiesIndex.get(it.asString(), project, scope) } ++ .flatMap { LightClassUtil.getLightClassPropertyMethods(it).allDeclarations } ++ .filter { it.name == name } ++ .map { it as? PsiMethod } ++ ++ return (propertyAccessorsPsi + kotlinFunctionsPsi).filterNotNull().toList().toTypedArray() ++ } ++ ++ override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array { ++ val methods = getMethodsByName(name, scope) ++ if (methods.size > maxCount) ++ return PsiMethod.EMPTY_ARRAY ++ return methods ++ } ++ ++ override fun getFieldsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array { ++ val fields = getFieldsByName(name, scope) ++ if (fields.size > maxCount) ++ return PsiField.EMPTY_ARRAY ++ return fields ++ } + + override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor): Boolean + = ContainerUtil.process(getMethodsByName(name, scope), processor) + +- override fun getAllMethodNames(): Array +- = emptyArray() ++ override fun getAllMethodNames(): Array { ++ val functionIndex = KotlinFunctionShortNameIndex.getInstance() ++ val functionNames = functionIndex.getAllKeys(project) ++ ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val globalScope = GlobalSearchScope.allScope(project) ++ val propertyAccessorNames = propertiesIndex.getAllKeys(project) ++ .flatMap { propertiesIndex.get(it, project, globalScope) }","This will be extremely slow. It's OK to return names for which `getMethodsByName()` will then not find any methods, but it's not OK to look up every single method in the index. You should only use `getAllKeys()` and then calculate possible accessor names from those, without any lookups to the property index. +",2016-09-05 17:35:10 +602,"@@ -85,30 +87,78 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() + dest.addAll(allClassNames) + } + +- override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array +- = emptyArray() ++ override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array { ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val functionIndex = KotlinFunctionShortNameIndex.getInstance() + +- override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array +- = emptyArray() ++ val kotlinFunctionsPsi = functionIndex.get(name, project, scope) ++ .flatMap { LightClassUtil.getLightClassMethods(it) } + +- override fun getFieldsByNameIfNotMoreThan(s: String, scope: GlobalSearchScope, i: Int): Array +- = emptyArray() ++ val propertyAccessorsPsi = getPropertyNamesCandidatesByAccessorName(Name.identifier(name)) ++ .flatMap { propertiesIndex.get(it.asString(), project, scope) } ++ .flatMap { LightClassUtil.getLightClassPropertyMethods(it).allDeclarations } ++ .filter { it.name == name } ++ .map { it as? PsiMethod } ++ ++ return (propertyAccessorsPsi + kotlinFunctionsPsi).filterNotNull().toList().toTypedArray() ++ } ++ ++ override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array { ++ val methods = getMethodsByName(name, scope) ++ if (methods.size > maxCount) ++ return PsiMethod.EMPTY_ARRAY ++ return methods ++ } ++ ++ override fun getFieldsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array { ++ val fields = getFieldsByName(name, scope) ++ if (fields.size > maxCount) ++ return PsiField.EMPTY_ARRAY ++ return fields ++ } + + override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor): Boolean + = ContainerUtil.process(getMethodsByName(name, scope), processor) + +- override fun getAllMethodNames(): Array +- = emptyArray() ++ override fun getAllMethodNames(): Array { ++ val functionIndex = KotlinFunctionShortNameIndex.getInstance() ++ val functionNames = functionIndex.getAllKeys(project) ++ ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val globalScope = GlobalSearchScope.allScope(project) ++ val propertyAccessorNames = propertiesIndex.getAllKeys(project) ++ .flatMap { propertiesIndex.get(it, project, globalScope) } ++ .flatMap { it.getAccessorNames() } ++ ++ return (functionNames + propertyAccessorNames).toTypedArray() ++ } + + override fun getAllMethodNames(set: HashSet) { ++ set.addAll(allMethodNames) ++ } ++ ++ override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array { ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ ++ return propertiesIndex.get(name, project, scope) ++ .map { LightClassUtil.getLightClassBackingField(it) } ++ .filterNotNull() ++ .toTypedArray() + } + +- override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array +- = emptyArray() ++ override fun getAllFieldNames(): Array { ++ val propertiesIndex = KotlinPropertyShortNameIndex.getInstance() ++ val globalScope = GlobalSearchScope.allScope(project) + +- override fun getAllFieldNames(): Array +- = emptyArray() ++ return propertiesIndex.getAllKeys(project) ++ .flatMap { propertiesIndex.get(it, project, globalScope) }","Same here. No property index lookups please. +",2016-09-05 17:36:15 +521,"@@ -854,4 +854,38 @@ class CollectionTest { + // we need toString() inside pattern because of KT-8666 + assertEquals(""[1, a, null, ${Long.MAX_VALUE.toString()}]"", listOf(1, ""a"", null, Long.MAX_VALUE).toString()) + } ++ ++ @test fun testGetRange() { ++ val listStr = listOf(""a"", ""b"", ""c"", ""d"", ""e"") ++ ++ assertTrue(throwsError{listStr[-1..2]}) ++ assertTrue(throwsError{listStr[1..10]}) ++ ++ assertTrue(listStr[1..3] == listOf(""b"", ""c"", ""d"")) ++ assertTrue(listStr[1..3] is List) ++ assertTrue(listStr[1..3][0..1] == listOf(""b"", ""c"")) ++ assertTrue(listStr[1..3][0..1] is List) ++ assertTrue(listStr[1..3][0..1][0] is String) ++ assertTrue(listStr[1..3][0..1][0] == ""b"") ++ ++ assertTrue(listStr[1..1] == listOf(listStr[1])) ++ assertTrue(listStr[3..1] == listOf()) ++ } ++ ++ fun throwsError(f :()->Unit): Boolean { ++ try{ ++ f() ++ } catch(e: Exception){ ++ return true ++ } ++ return false ++ } ++ ++ @test fun testListTimes(){ ++ val shortlistStr = listOf(""a"", ""b"") ++ assertTrue(shortlistStr*0 == listOf())","`assertEquals(expected, actual)` is preferred as it dumps diff on failure +",2016-02-27 13:54:32 +523,"@@ -854,4 +854,41 @@ class CollectionTest { + // we need toString() inside pattern because of KT-8666 + assertEquals(""[1, a, null, ${Long.MAX_VALUE.toString()}]"", listOf(1, ""a"", null, Long.MAX_VALUE).toString()) + } ++ ++ @test fun testGetRange() { ++ val listStr = listOf(""a"", ""b"", ""c"", ""d"", ""e"")","I believe we also need tests on an empty list: should fail at any range but empty range on empty list should produce empty list +",2016-02-27 17:22:10 +522,"@@ -854,4 +854,41 @@ class CollectionTest { + // we need toString() inside pattern because of KT-8666 + assertEquals(""[1, a, null, ${Long.MAX_VALUE.toString()}]"", listOf(1, ""a"", null, Long.MAX_VALUE).toString()) + } ++ ++ @test fun testGetRange() { ++ val listStr = listOf(""a"", ""b"", ""c"", ""d"", ""e"") ++ ++ assertTrue(throwsError{listStr[-1..2]}) ++ assertTrue(throwsError{listStr[1..10]}) ++ ++ assertEquals(listStr[IntRange.EMPTY], listOf())","I should be expected value at the first place, the second argument is actual, swap these arguments please +",2016-02-27 17:20:29 +427,"@@ -86,6 +86,8 @@ + + + ++ ++ ","There's another fileset which is used in the `compiler-quick` target and declared just below, please also add these modules there. + +Also please add them to `compiler-sources`. +",2015-08-22 02:20:42 +401,"@@ -86,7 +86,8 @@ protected void configureSpecificCompilerArguments(@NotNull K2JSCompilerArguments + collector.add(new File(outputFile).getParent()); + } + if (metaInfo) { +- String metaFile = KotlinPackage.substringBeforeLast(outputFile, JavaScript.DOT_EXTENSION, outputFile) + KotlinJavascriptMetadataUtils.META_JS_SUFFIX; ++ String output = com.google.common.base.Objects.firstNonNull(outputFile, """"); // fqname here because of J8 compatibility issues","Is it not possible with Kotlin stdlib? +",2015-07-27 19:30:49 +996,"@@ -867,7 +912,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter { + if (parameters.size == 1 && !isKotlinFunctionType) { + // for lambdas all parameters with types should be present + emptyList() +- } else { ++ } ++ else {",Please restore previous code formatting - actual `if-else` statements and spaces are against accepted conceptions.,2017-08-16 16:24:17 +384,"@@ -87,15 +87,24 @@ public boolean execute() throws BuildException { + + kotlinc.getAdditionalArguments().addAll(additionalArguments); + +- kotlinc.execute(); +- if (!Integer.valueOf(0).equals(kotlinc.getExitCode())) { +- // Don't run javac if failOnError = false and there were errors on Kotlin sources +- return false; ++ // Javac13#execute passes everything in compileList to javac, which doesn't recognize .kt files ++ File[] compileListForJavac = filterOutKotlinSources(compileList); ++ ++ boolean hasKotlinFilesInSources = compileListForJavac.length < compileList.length; ++ ++ if (hasKotlinFilesInSources) { ++ kotlinc.execute(); ++ if (!Integer.valueOf(0).equals(kotlinc.getExitCode())) { ++ // Don't run javac if failOnError = false and there were errors on Kotlin sources ++ return false; ++ } ++ } ++ else { ++ kotlinc.fillArguments();","what for this? +",2015-06-11 10:28:18 +383,"@@ -87,15 +87,24 @@ public boolean execute() throws BuildException { + + kotlinc.getAdditionalArguments().addAll(additionalArguments); + +- kotlinc.execute(); +- if (!Integer.valueOf(0).equals(kotlinc.getExitCode())) { +- // Don't run javac if failOnError = false and there were errors on Kotlin sources +- return false; ++ // Javac13#execute passes everything in compileList to javac, which doesn't recognize .kt files ++ File[] compileListForJavac = filterOutKotlinSources(compileList); ++ ++ boolean hasKotlinFilesInSources = compileListForJavac.length < compileList.length; ++ ++ if (hasKotlinFilesInSources) { ++ kotlinc.execute(); ++ if (!Integer.valueOf(0).equals(kotlinc.getExitCode())) { ++ // Don't run javac if failOnError = false and there were errors on Kotlin sources ++ return false; ++ } ++ } ++ else { ++ kotlinc.fillArguments(); + } + + javac.log(""Running javac...""); + +- // Javac13#execute passes everything in compileList to javac, which doesn't recognize .kt files + compileList = filterOutKotlinSources(compileList);","why do you filter it twice? +",2015-06-11 10:26:09 +679,"@@ -88,8 +85,10 @@ class ConvertFunctionToPropertyIntention : SelfTargetingIntention Boolean): Array? = listF + override fun accept(file: File) = filter(file) + } + ) ++ ++/** ++ * Returns true if the file is a directory and contains a child file with a given name. Otherwise false is returned. ++ */ ++public fun File.contains(name: String): Boolean {","Name of the function is not very good. First, it can be perceived if ""path"" contains ""name"", not contents of the folder. Second, it will fit ""in"" by convention, and while `if (""build.gradle"" in folder)` looks nice, for the overload with predicate it is a little bit strange. Consider using a different name. +",2014-11-26 14:56:02 +951,"@@ -92,6 +95,14 @@ fun KtLambdaArgument.moveInsideParenthesesAndReplaceWith( + return oldCallExpression.replace(newCallExpression) as KtCallExpression + } + ++private fun shouldLambdaParameterNamed(args: List, callExpr: KtCallExpression): Boolean { ++ return args.any { it.isNamed() } ||","Now that it's a separate function, there's no need to cramp it all into a single expression. + +``` +if (args.any { it.isNamed () }) return true +val callee = ...resolve as? KtFunction ?: return true +return callee.valueParameters.any { ... } +``` + +Also the grammatically correct name would be `shouldLambdaParameterBeNamed`.",2017-08-04 13:44:39 +544,"@@ -95,6 +95,48 @@ class CollectionTest { + } + } + ++ @test fun filterIsInstanceList() { ++ val values: List = listOf(1, 2, 3.0, ""abc"", ""cde"") ++ ++ val numberValues: List = values.filterIsInstance() ++ assertEquals(listOf(1, 2, 3.0), numberValues) ++ ++ // doesn't distinguish double from int in JS ++// val doubleValues: List = values.filterIsInstance() ++// assertEquals(listOf(3.0), doubleValues) ++ ++ val stringValues: List = values.filterIsInstance() ++ assertEquals(listOf(""abc"", ""cde""), stringValues) ++ ++ // is Any doesn't work in JS ++// val anyValues: List = values.filterIsInstance()","ok, could be mentioned +",2016-04-25 23:33:53 +868,"@@ -96,6 +97,9 @@ class RecursivePropertyAccessorInspection : AbstractKotlinInspection() { + val bindingContext = element.analyze() + val target = bindingContext[REFERENCE_TARGET, element]",y :-*,2017-06-04 11:54:12 +869,"@@ -96,6 +97,9 @@ class RecursivePropertyAccessorInspection : AbstractKotlinInspection() { + val bindingContext = element.analyze() + val target = bindingContext[REFERENCE_TARGET, element] + if (target != bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, propertyAccessor.property]) return false ++ (element.parent as? KtDotQualifiedExpression)?.let { ++ if (it.receiverExpression.text != KtTokens.THIS_KEYWORD.value && !it.isCompanionObjectReceiver(bindingContext)) return false ++ } + return isSameAccessor(element, propertyAccessor.isGetter)",sufjfubi,2017-06-04 11:54:22 +24,"@@ -96,7 +96,10 @@ public boolean accept(File pathname) { + List subdirs = Arrays.asList(files); + Collections.sort(subdirs); + for (File subdir : subdirs) { +- suite.addTest(suiteForDirectory(baseDataDir, dataPath + ""/"" + subdir.getName(), recursive, filter, factory));","This change must sit in a separate commit, as it has no relation to the problem being solved by this one +",2013-01-29 14:00:10 +593,"@@ -97,12 +97,28 @@ class KotlinFoldingBuilder : CustomFoldingBuilder(), DumbAware { + } + + override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange): String = when { +- node.elementType == KtTokens.BLOCK_COMMENT -> ""/.../"" +- node.elementType == KDocTokens.KDOC -> ""/**...*/"" ++ node.elementType == KtTokens.BLOCK_COMMENT -> ""/${getFirstLineOfComment(node)}.../"" ++ node.elementType == KDocTokens.KDOC -> ""/**${getFirstLineOfComment(node)}...*/"" + node.psi is KtImportList -> ""..."" + else -> ""{...}"" + } + ++ private fun getFirstLineOfComment(node: ASTNode): String { ++ val targetCommentLine = node.text.split(""\n"").firstOrNull { ++ getCommentContents(it).isNotEmpty() ++ } ?: return """" ++ return getCommentContents(targetCommentLine) ++ } ++ ++ private fun getCommentContents(line: String): String { ++ val comment = KotlinCommenter()","There is no need to create a new object here; it's OK to hard-code the token texts. +",2016-08-19 16:20:42 +594,"@@ -97,12 +97,28 @@ class KotlinFoldingBuilder : CustomFoldingBuilder(), DumbAware { + } + + override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange): String = when { +- node.elementType == KtTokens.BLOCK_COMMENT -> ""/.../"" +- node.elementType == KDocTokens.KDOC -> ""/**...*/"" ++ node.elementType == KtTokens.BLOCK_COMMENT -> ""/${getFirstLineOfComment(node)}.../"" ++ node.elementType == KDocTokens.KDOC -> ""/**${getFirstLineOfComment(node)}...*/"" + node.psi is KtImportList -> ""..."" + else -> ""{...}"" + } + ++ private fun getFirstLineOfComment(node: ASTNode): String { ++ val targetCommentLine = node.text.split(""\n"").firstOrNull { ++ getCommentContents(it).isNotEmpty() ++ } ?: return """" ++ return getCommentContents(targetCommentLine) ++ } ++ ++ private fun getCommentContents(line: String): String { ++ val comment = KotlinCommenter() ++ return line.trim() ++ .replace(comment.documentationCommentPrefix!!, """") ++ .replace(comment.blockCommentPrefix!!, """") ++ .replace(comment.blockCommentSuffix!!, """") ++ .replace(comment.documentationCommentLinePrefix!!, """")","Please make sure that the line has at most one leading and at most one trailing space after you've remove the prefix and suffix +",2016-08-19 16:21:18 +499,"@@ -97,3 +96,24 @@ inline fun AbstractInsnNode.findPreviousOrNull(predicate: (AbstractInsnNode) -> + + fun AbstractInsnNode.hasOpcode(): Boolean = + getOpcode() >= 0 ++ ++// See InstructionAdapter ++// ++// public void iconst(final int cst) { ++// if (cst >= -1 && cst <= 5) { ++// mv.visitInsn(Opcodes.ICONST_0 + cst); ++// } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) { ++// mv.visitIntInsn(Opcodes.BIPUSH, cst); ++// } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) { ++// mv.visitIntInsn(Opcodes.SIPUSH, cst); ++// } else { ++// mv.visitLdcInsn(new Integer(cst)); ++// } ++// } ++val AbstractInsnNode.intConstant: Int? get() = ++ when (opcode) { ++ in ICONST_0..ICONST_5 -> opcode - ICONST_0","What about `ICONST_M1`? +",2015-12-28 14:54:59 +498,"@@ -97,3 +96,24 @@ inline fun AbstractInsnNode.findPreviousOrNull(predicate: (AbstractInsnNode) -> + + fun AbstractInsnNode.hasOpcode(): Boolean = + getOpcode() >= 0 ++ ++// See InstructionAdapter ++// ++// public void iconst(final int cst) { ++// if (cst >= -1 && cst <= 5) { ++// mv.visitInsn(Opcodes.ICONST_0 + cst); ++// } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) { ++// mv.visitIntInsn(Opcodes.BIPUSH, cst); ++// } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) { ++// mv.visitIntInsn(Opcodes.SIPUSH, cst); ++// } else { ++// mv.visitLdcInsn(new Integer(cst)); ++// } ++// } ++val AbstractInsnNode.intConstant: Int? get() = ++ when (opcode) { ++ in ICONST_0..ICONST_5 -> opcode - ICONST_0 ++ BIPUSH, SIPUSH -> (this as IntInsnNode).operand ++ LDC -> (this as LdcInsnNode).cst as? Int?","`as? Int` should work I think +",2015-12-28 14:54:41 +874,"@@ -97,7 +98,15 @@ fun KotlinType.isResolvableInScope(scope: LexicalScope?, checkTypeParameters: Bo + + val descriptor = constructor.declarationDescriptor + if (descriptor == null || descriptor.name.isSpecial) return false +- if (!checkTypeParameters && descriptor is TypeParameterDescriptor) return true ++ ++ if (descriptor is TypeParameterDescriptor) { ++ if (checkTypeParameters) { ++ val owner = descriptor.containingDeclaration ++ if (owner is FunctionDescriptor && owner.typeParameters.any { it == descriptor }) return true",any { it == descriptor } is equivalent to just contains(descriptor),2017-06-26 14:20:03 +875,"@@ -97,7 +98,15 @@ fun KotlinType.isResolvableInScope(scope: LexicalScope?, checkTypeParameters: Bo + + val descriptor = constructor.declarationDescriptor + if (descriptor == null || descriptor.name.isSpecial) return false +- if (!checkTypeParameters && descriptor is TypeParameterDescriptor) return true ++ ++ if (descriptor is TypeParameterDescriptor) { ++ if (checkTypeParameters) { ++ val owner = descriptor.containingDeclaration ++ if (owner is FunctionDescriptor && owner.typeParameters.any { it == descriptor }) return true ++ } else {","FYI: in Kotlin project if...else is formatted in a different way: +``` +if () { +} +else { +} +```",2017-06-26 14:20:37 +287,"@@ -988,7 +988,7 @@ public inline fun Stream.firstOrNull(predicate: (T) -> Boolean): T? { + } + + /** +- * Returns first element matching the given *predicate*, or *null* if element was not found ++ * Returns first character matching the given [predicate], or *null* if character was not found","May be replace _null_ with `null`? +",2015-02-09 15:47:09 +597,"@@ -99,10 +100,18 @@ class KotlinFoldingBuilder : CustomFoldingBuilder(), DumbAware { + override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange): String = when { + node.elementType == KtTokens.BLOCK_COMMENT -> ""/${getFirstLineOfComment(node)}.../"" + node.elementType == KDocTokens.KDOC -> ""/**${getFirstLineOfComment(node)}...*/"" ++ node.elementType == KtNodeTypes.STRING_TEMPLATE -> ""\""\""\""${getFirstLineOfString(node)}...\""\""\"""" + node.psi is KtImportList -> ""..."" + else -> ""{...}"" + } + ++ private fun getFirstLineOfString(node: ASTNode): String { ++ val targetStringLine = node.text.split(""\n"").firstOrNull {","You can avoid multiple `replace` calls if you use `asSequence().map { it.replace(...) }.firstOrNull { it.isNotBlank }` +",2016-08-29 11:06:06 +598,"@@ -99,10 +100,18 @@ class KotlinFoldingBuilder : CustomFoldingBuilder(), DumbAware { + override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange): String = when { + node.elementType == KtTokens.BLOCK_COMMENT -> ""/${getFirstLineOfComment(node)}.../"" + node.elementType == KDocTokens.KDOC -> ""/**${getFirstLineOfComment(node)}...*/"" ++ node.elementType == KtNodeTypes.STRING_TEMPLATE -> ""\""\""\""${getFirstLineOfString(node)}...\""\""\"""" + node.psi is KtImportList -> ""..."" + else -> ""{...}"" + } + ++ private fun getFirstLineOfString(node: ASTNode): String { ++ val targetStringLine = node.text.split(""\n"").firstOrNull { ++ it.replace(""\""\""\"""", """").isNotBlank() ++ } ?: return """" ++ return "" ${targetStringLine.replace(""\""\""\"""", """").trim()} ""","It's better to add surrounding spaces in `getLanguagePlaceholderText()`, not in this function. (This applies also to `getFirstLineOfComment()`.) +",2016-08-29 11:06:55 diff --git a/data/microsoft_vscode_1000.csv b/data/microsoft_vscode_1000.csv new file mode 100644 index 0000000..de5e1b6 --- /dev/null +++ b/data/microsoft_vscode_1000.csv @@ -0,0 +1,24091 @@ +,diff_hunk,human_review,created_at +422,"@@ -0,0 +1 @@ ++","Are you reusing an icon here? +",2016-10-24 15:59:57 +421,"@@ -0,0 +1 @@ ++","Are you reusing an icon here? +",2016-10-24 15:59:51 +208,"@@ -0,0 +1,101 @@ ++/*---------------------------------------------------------------------------------------------","Awesome work :+1: +",2016-07-08 13:57:42 +403,"@@ -0,0 +1,101 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TreeExplorerNodeProvider } from 'vscode'; ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { Disposable } from 'vs/workbench/api/node/extHostTypes'; ++import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; ++import { MainContext, ExtHostTreeExplorersShape, MainThreadTreeExplorersShape } from './extHost.protocol'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; ++import { asWinJsPromise } from 'vs/base/common/async'; ++import { Severity } from 'vs/platform/message/common/message'; ++ ++export class ExtHostTreeExplorers extends ExtHostTreeExplorersShape { ++ private _proxy: MainThreadTreeExplorersShape; ++ ++ private _treeExplorerNodeProviders: { [providerId: string]: TreeExplorerNodeProvider }; ++ private _externalNodeMaps: { [providerId: string]: { [id: number]: any } }; ++ ++ constructor( ++ threadService: IThreadService, ++ private commands: ExtHostCommands ++ ) { ++ super(); ++ ++ this._proxy = threadService.get(MainContext.MainThreadExplorers); ++ ++ this._treeExplorerNodeProviders = Object.create(null); ++ this._externalNodeMaps = Object.create(null); ++ } ++ ++ registerTreeExplorerNodeProvider(providerId: string, provider: TreeExplorerNodeProvider): Disposable {","Shouldn't this return `vscode.Disposable` from `import * as vscode from 'vscode';`? +",2016-10-24 15:36:37 +404,"@@ -0,0 +1,101 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TreeExplorerNodeProvider } from 'vscode'; ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { Disposable } from 'vs/workbench/api/node/extHostTypes'; ++import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; ++import { MainContext, ExtHostTreeExplorersShape, MainThreadTreeExplorersShape } from './extHost.protocol'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; ++import { asWinJsPromise } from 'vs/base/common/async'; ++import { Severity } from 'vs/platform/message/common/message'; ++ ++export class ExtHostTreeExplorers extends ExtHostTreeExplorersShape { ++ private _proxy: MainThreadTreeExplorersShape; ++ ++ private _treeExplorerNodeProviders: { [providerId: string]: TreeExplorerNodeProvider }; ++ private _externalNodeMaps: { [providerId: string]: { [id: number]: any } }; ++ ++ constructor( ++ threadService: IThreadService, ++ private commands: ExtHostCommands ++ ) { ++ super(); ++ ++ this._proxy = threadService.get(MainContext.MainThreadExplorers); ++ ++ this._treeExplorerNodeProviders = Object.create(null); ++ this._externalNodeMaps = Object.create(null); ++ } ++ ++ registerTreeExplorerNodeProvider(providerId: string, provider: TreeExplorerNodeProvider): Disposable { ++ this._proxy.$registerTreeExplorerNodeProvider(providerId); ++ this._treeExplorerNodeProviders[providerId] = provider; ++ ++ return new Disposable(() => { ++ delete this._treeExplorerNodeProviders[providerId];","Don't you need to clean up `_externalNodeMaps` too? +",2016-10-24 15:37:16 +400,"@@ -0,0 +1,101 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TreeExplorerNodeProvider } from 'vscode'; ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { Disposable } from 'vs/workbench/api/node/extHostTypes'; ++import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; ++import { MainContext, ExtHostTreeExplorersShape, MainThreadTreeExplorersShape } from './extHost.protocol'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; ++import { asWinJsPromise } from 'vs/base/common/async'; ++import { Severity } from 'vs/platform/message/common/message'; ++ ++export class ExtHostTreeExplorers extends ExtHostTreeExplorersShape { ++ private _proxy: MainThreadTreeExplorersShape; ++ ++ private _treeExplorerNodeProviders: { [providerId: string]: TreeExplorerNodeProvider }; ++ private _externalNodeMaps: { [providerId: string]: { [id: number]: any } }; ++ ++ constructor( ++ threadService: IThreadService, ++ private commands: ExtHostCommands ++ ) { ++ super(); ++ ++ this._proxy = threadService.get(MainContext.MainThreadExplorers); ++ ++ this._treeExplorerNodeProviders = Object.create(null); ++ this._externalNodeMaps = Object.create(null); ++ } ++ ++ registerTreeExplorerNodeProvider(providerId: string, provider: TreeExplorerNodeProvider): Disposable { ++ this._proxy.$registerTreeExplorerNodeProvider(providerId); ++ this._treeExplorerNodeProviders[providerId] = provider; ++ ++ return new Disposable(() => { ++ delete this._treeExplorerNodeProviders[providerId]; ++ }); ++ } ++ ++ $provideRootNode(providerId: string): TPromise { ++ const provider = this.getProvider(providerId); ++ ++ return asWinJsPromise(() => provider.provideRootNode()).then(externalRootNode => { ++ const treeNodeMap = Object.create(null); ++ this._externalNodeMaps[providerId] = treeNodeMap; ++ ++ const internalRootNode = new InternalTreeExplorerNode(externalRootNode, provider); ++ this._externalNodeMaps[providerId][internalRootNode.id] = externalRootNode; ++ return internalRootNode; ++ }, err => { ++ this.showErrorMessage(`TreeExplorerNodeProvider '${providerId}' failed to provide root node.`); ++ }); ++ } ++ ++ $resolveChildren(providerId: string, mainThreadNode: InternalTreeExplorerNode): TPromise { ++ const provider = this.getProvider(providerId); ++ ++ const externalNodeMap = this._externalNodeMaps[providerId]; ++ const externalNode = externalNodeMap[mainThreadNode.id]; ++ ++ return asWinJsPromise(() => provider.resolveChildren(externalNode)).then(children => { ++ return children.map(externalChild => { ++ const internalChild = new InternalTreeExplorerNode(externalChild, provider); ++ externalNodeMap[internalChild.id] = externalChild; ++ return internalChild; ++ }); ++ }, err => { ++ this.showErrorMessage(`TreeExplorerNodeProvider '${providerId}' failed to resolve children.`); ++ }); ++ } ++ ++ $executeCommand(providerId: string, mainThreadNode: InternalTreeExplorerNode): TPromise { ++ if (mainThreadNode.clickCommand) { ++ const externalNode = this._externalNodeMaps[providerId][mainThreadNode.id]; ++ return asWinJsPromise(() => this.commands.executeCommand(mainThreadNode.clickCommand, externalNode)).then(() => { ++ return null; ++ }, err => { ++ this.showErrorMessage(`Failed to execute command '${mainThreadNode.clickCommand}' provided by TreeExplorerNodeProvider '${providerId}'.`); ++ }); ++ } ++ ++ return TPromise.as(null); ++ } ++ ++ getProvider(providerId: string): TreeExplorerNodeProvider { ++ const provider = this._treeExplorerNodeProviders[providerId]; ++ if (!provider) { ++ this.showErrorMessage(`No TreeExplorerNodeProvider with id '${providerId}' registered.`); ++ } ++ ++ return provider; ++ } ++ ++ private showErrorMessage(message: string): void { ++ this._proxy.$showMessage(Severity.Error, message);","You could probably make ExtHostMessageService a dependency and call into that from here? +",2016-10-24 15:30:49 +803,"@@ -0,0 +1,102 @@ ++/*---------------------------------------------------------------------------------------------","Seems like a lot of overlap with https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/electron-browser/bootstrap/index.js#L48, maybe better to have a common base that both can reuse?",2017-03-07 06:36:13 +427,"@@ -0,0 +1,102 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TreeExplorerNodeProvider } from 'vscode'; ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { Disposable } from 'vs/workbench/api/node/extHostTypes'; ++import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; ++import { MainContext, ExtHostTreeExplorersShape, MainThreadTreeExplorersShape } from './extHost.protocol'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; ++import { asWinJsPromise } from 'vs/base/common/async'; ++import { Severity } from 'vs/platform/message/common/message'; ++ ++export class ExtHostTreeExplorers extends ExtHostTreeExplorersShape { ++ private _proxy: MainThreadTreeExplorersShape; ++ ++ private _treeExplorerNodeProviders: { [providerId: string]: TreeExplorerNodeProvider }; ++ private _externalNodeMaps: { [providerId: string]: { [id: number]: any } }; ++ ++ constructor( ++ threadService: IThreadService, ++ private commands: ExtHostCommands ++ ) { ++ super(); ++ ++ this._proxy = threadService.get(MainContext.MainThreadExplorers); ++ ++ this._treeExplorerNodeProviders = Object.create(null); ++ this._externalNodeMaps = Object.create(null); ++ } ++ ++ registerTreeExplorerNodeProvider(providerId: string, provider: TreeExplorerNodeProvider): Disposable { ++ this._proxy.$registerTreeExplorerNodeProvider(providerId); ++ this._treeExplorerNodeProviders[providerId] = provider; ++ ++ return new Disposable(() => { ++ delete this._treeExplorerNodeProviders[providerId]; ++ delete this._treeExplorerNodeProviders[providerId]; ++ }); ++ } ++ ++ $provideRootNode(providerId: string): TPromise { ++ const provider = this.getProvider(providerId); ++ ++ return asWinJsPromise(() => provider.provideRootNode()).then(externalRootNode => { ++ const treeNodeMap = Object.create(null); ++ this._externalNodeMaps[providerId] = treeNodeMap; ++ ++ const internalRootNode = new InternalTreeExplorerNode(externalRootNode, provider); ++ this._externalNodeMaps[providerId][internalRootNode.id] = externalRootNode; ++ return internalRootNode; ++ }, err => { ++ this.showErrorMessage(`TreeExplorerNodeProvider '${providerId}' failed to provide root node.`);","[needs change] Replace with `return TPromise.wrapError('TreeEx...')` +",2016-11-01 09:49:31 +428,"@@ -0,0 +1,102 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TreeExplorerNodeProvider } from 'vscode'; ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { Disposable } from 'vs/workbench/api/node/extHostTypes'; ++import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; ++import { MainContext, ExtHostTreeExplorersShape, MainThreadTreeExplorersShape } from './extHost.protocol'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; ++import { asWinJsPromise } from 'vs/base/common/async'; ++import { Severity } from 'vs/platform/message/common/message'; ++ ++export class ExtHostTreeExplorers extends ExtHostTreeExplorersShape { ++ private _proxy: MainThreadTreeExplorersShape; ++ ++ private _treeExplorerNodeProviders: { [providerId: string]: TreeExplorerNodeProvider }; ++ private _externalNodeMaps: { [providerId: string]: { [id: number]: any } }; ++ ++ constructor( ++ threadService: IThreadService, ++ private commands: ExtHostCommands ++ ) { ++ super(); ++ ++ this._proxy = threadService.get(MainContext.MainThreadExplorers); ++ ++ this._treeExplorerNodeProviders = Object.create(null); ++ this._externalNodeMaps = Object.create(null); ++ } ++ ++ registerTreeExplorerNodeProvider(providerId: string, provider: TreeExplorerNodeProvider): Disposable { ++ this._proxy.$registerTreeExplorerNodeProvider(providerId); ++ this._treeExplorerNodeProviders[providerId] = provider; ++ ++ return new Disposable(() => { ++ delete this._treeExplorerNodeProviders[providerId]; ++ delete this._treeExplorerNodeProviders[providerId]; ++ }); ++ } ++ ++ $provideRootNode(providerId: string): TPromise { ++ const provider = this.getProvider(providerId); ++ ++ return asWinJsPromise(() => provider.provideRootNode()).then(externalRootNode => { ++ const treeNodeMap = Object.create(null); ++ this._externalNodeMaps[providerId] = treeNodeMap; ++ ++ const internalRootNode = new InternalTreeExplorerNode(externalRootNode, provider); ++ this._externalNodeMaps[providerId][internalRootNode.id] = externalRootNode; ++ return internalRootNode; ++ }, err => { ++ this.showErrorMessage(`TreeExplorerNodeProvider '${providerId}' failed to provide root node.`); ++ }); ++ } ++ ++ $resolveChildren(providerId: string, mainThreadNode: InternalTreeExplorerNode): TPromise { ++ const provider = this.getProvider(providerId); ++ ++ const externalNodeMap = this._externalNodeMaps[providerId]; ++ const externalNode = externalNodeMap[mainThreadNode.id]; ++ ++ return asWinJsPromise(() => provider.resolveChildren(externalNode)).then(children => { ++ return children.map(externalChild => { ++ const internalChild = new InternalTreeExplorerNode(externalChild, provider); ++ externalNodeMap[internalChild.id] = externalChild; ++ return internalChild; ++ }); ++ }, err => { ++ this.showErrorMessage(`TreeExplorerNodeProvider '${providerId}' failed to resolve children.`);","[needs change] Like above `return Promise.wrapError(...)` +",2016-11-01 09:50:08 +52,"@@ -0,0 +1,107 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import nls = require('vs/nls'); ++import {Promise} from 'vs/base/common/winjs.base'; ++import {Action} from 'vs/base/common/actions'; ++import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; ++import {Registry} from 'vs/platform/platform'; ++import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; ++import {IPanel} from 'vs/workbench/common/panel'; ++import {IWorkbenchActionRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/actionRegistry'; ++import {Composite, CompositeDescriptor, CompositeRegistry} from 'vs/workbench/browser/composite'; ++import {IPartService} from 'vs/workbench/services/part/common/partService'; ++import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService'; ++ ++export abstract class Panel extends Composite implements IPanel { } ++ ++/** ++ * A panel descriptor is a leightweight descriptor of a panel in the monaco workbench. ++ */ ++export class PanelDescriptor extends CompositeDescriptor { } ++ ++export class PanelRegistry extends CompositeRegistry { ++ private defaultPanelId: string; ++ ++ /** ++ * Registers a panel to the platform. ++ */ ++ public registerPanel(descriptor: PanelDescriptor): void { ++ super.registerComposite(descriptor); ++ } ++ ++ /** ++ * Returns the panel descriptor for the given id or null if none. ++ */ ++ public getPanel(id: string): PanelDescriptor { ++ return this.getComposite(id); ++ } ++ ++ /** ++ * Returns an array of registered panels known to the platform. ++ */ ++ public getPanels(): PanelDescriptor[] { ++ return this.getComposits(); ++ } ++ ++ /** ++ * Sets the id of the panel that should open on startup by default. ++ */ ++ public setDefaultPanelId(id: string): void { ++ this.defaultPanelId = id; ++ } ++ ++ /** ++ * Gets the id of the panel that should open on startup by default. ++ */ ++ public getDefaultPanelId(): string { ++ return this.defaultPanelId; ++ } ++} ++ ++export const Extensions = { ++ Panels: 'workbench.contributions.panels' ++}; ++ ++export class ClosePanelAction extends Action {","@isidorn Suggest to move these actions into panelPart. You can see that sidebarPart is also contributing an action! +",2016-01-19 11:10:10 +50,"@@ -0,0 +1,107 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import nls = require('vs/nls'); ++import {Promise} from 'vs/base/common/winjs.base'; ++import {Action} from 'vs/base/common/actions'; ++import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; ++import {Registry} from 'vs/platform/platform'; ++import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; ++import {IPanel} from 'vs/workbench/common/panel'; ++import {IWorkbenchActionRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/actionRegistry'; ++import {Composite, CompositeDescriptor, CompositeRegistry} from 'vs/workbench/browser/composite'; ++import {IPartService} from 'vs/workbench/services/part/common/partService'; ++import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService'; ++ ++export abstract class Panel extends Composite implements IPanel { } ++ ++/** ++ * A panel descriptor is a leightweight descriptor of a panel in the monaco workbench. ++ */ ++export class PanelDescriptor extends CompositeDescriptor { } ++ ++export class PanelRegistry extends CompositeRegistry { ++ private defaultPanelId: string; ++ ++ /** ++ * Registers a panel to the platform. ++ */ ++ public registerPanel(descriptor: PanelDescriptor): void { ++ super.registerComposite(descriptor); ++ } ++ ++ /** ++ * Returns the panel descriptor for the given id or null if none. ++ */ ++ public getPanel(id: string): PanelDescriptor { ++ return this.getComposite(id); ++ } ++ ++ /** ++ * Returns an array of registered panels known to the platform. ++ */ ++ public getPanels(): PanelDescriptor[] { ++ return this.getComposits(); ++ } ++ ++ /** ++ * Sets the id of the panel that should open on startup by default. ++ */ ++ public setDefaultPanelId(id: string): void { ++ this.defaultPanelId = id; ++ } ++ ++ /** ++ * Gets the id of the panel that should open on startup by default. ++ */ ++ public getDefaultPanelId(): string { ++ return this.defaultPanelId; ++ } ++} ++ ++export const Extensions = { ++ Panels: 'workbench.contributions.panels' ++}; ++ ++export class ClosePanelAction extends Action { ++ static ID = 'workbench.action.closePanelAction'; ++ static LABEL = nls.localize('closePanel', ""Close""); ++ ++ constructor( ++ id: string, ++ name: string, ++ @IPartService private partService: IPartService ++ ) { ++ super(id, name, 'close-editor-action'); ++ } ++ ++ public run(): Promise { ++ this.partService.setPanelHidden(false);","I guess this should be ""true"" for closing? +",2016-01-19 11:03:48 +907,"@@ -0,0 +1,107 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import strings = require('vs/base/common/strings'); ++import uri from 'vs/base/common/uri'; ++import { isMacintosh } from 'vs/base/common/platform'; ++import * as errors from 'vs/base/common/errors'; ++import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; ++import * as nls from 'vs/nls'; ++import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++ ++export class LinkDetector { ++ private static FILE_LOCATION_PATTERNS: RegExp[] = [ ++ // group 0: the full thing :) ++ // group 1: absolute path ++ // group 2: drive letter on windows with trailing backslash or leading slash on mac/linux ++ // group 3: line number ++ // group 4: column number ++ // eg: at Context. (c:\Users\someone\Desktop\mocha-runner\test\test.js:26:11) ++ /(?![\(])(?:file:\/\/)?((?:([a-zA-Z]+:)|[^\(\)<>\'\""\[\]:\s]+)(?:[\\/][^\(\)<>\'\""\[\]:]*)?\.[a-zA-Z]+[0-9]*):(\d+)(?::(\d+))?/g","I notice that the comments are the same but the regex is now more complicated. +Could you please add some comments in code to clarify this regex beast",2017-05-05 09:38:51 +909,"@@ -0,0 +1,107 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import strings = require('vs/base/common/strings'); ++import uri from 'vs/base/common/uri'; ++import { isMacintosh } from 'vs/base/common/platform'; ++import * as errors from 'vs/base/common/errors'; ++import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; ++import * as nls from 'vs/nls'; ++import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++ ++export class LinkDetector { ++ private static FILE_LOCATION_PATTERNS: RegExp[] = [ ++ // group 0: the full thing :) ++ // group 1: absolute path ++ // group 2: drive letter on windows with trailing backslash or leading slash on mac/linux ++ // group 3: line number ++ // group 4: column number ++ // eg: at Context. (c:\Users\someone\Desktop\mocha-runner\test\test.js:26:11) ++ /(?![\(])(?:file:\/\/)?((?:([a-zA-Z]+:)|[^\(\)<>\'\""\[\]:\s]+)(?:[\\/][^\(\)<>\'\""\[\]:]*)?\.[a-zA-Z]+[0-9]*):(\d+)(?::(\d+))?/g ++ ]; ++ ++ constructor( ++ @IWorkbenchEditorService private editorService: IWorkbenchEditorService, ++ @IWorkspaceContextService private contextService: IWorkspaceContextService ++ ) { ++ // noop ++ } ++","Since this `handleLinks` is now a public method we could try to make the API a bit nicer, a personally find it ugly that it returns an `HTMLElement` or a `string`. It is hard to figure out what to expect as a return result for someobdy who just wants to use the link detector. +At least provide some comments to clarify each case, or try to always return an object with the corresponding fields. + +For ideas you can also check what does the terminal / editor link detector do and how does their API look like",2017-05-05 09:41:48 +908,"@@ -0,0 +1,107 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import strings = require('vs/base/common/strings'); ++import uri from 'vs/base/common/uri'; ++import { isMacintosh } from 'vs/base/common/platform'; ++import * as errors from 'vs/base/common/errors'; ++import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; ++import * as nls from 'vs/nls'; ++import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++ ++export class LinkDetector { ++ private static FILE_LOCATION_PATTERNS: RegExp[] = [ ++ // group 0: the full thing :) ++ // group 1: absolute path ++ // group 2: drive letter on windows with trailing backslash or leading slash on mac/linux ++ // group 3: line number ++ // group 4: column number ++ // eg: at Context. (c:\Users\someone\Desktop\mocha-runner\test\test.js:26:11) ++ /(?![\(])(?:file:\/\/)?((?:([a-zA-Z]+:)|[^\(\)<>\'\""\[\]:\s]+)(?:[\\/][^\(\)<>\'\""\[\]:]*)?\.[a-zA-Z]+[0-9]*):(\d+)(?::(\d+))?/g ++ ]; ++ ++ constructor( ++ @IWorkbenchEditorService private editorService: IWorkbenchEditorService, ++ @IWorkspaceContextService private contextService: IWorkspaceContextService ++ ) { ++ // noop ++ } ++ ++ public handleLinks(text: string): HTMLElement | string {","As far as I understand there have been no changes till the end of this file, it has just been moved over. +If that is the case it looks good to me",2017-05-05 09:40:14 +952,"@@ -0,0 +1,110 @@ ++/*---------------------------------------------------------------------------------------------","I like the idea of inferring the tsconfig.json to use from the open active TS file. However if no file is open I think we should still provide a reasonable command and not just look into the workspace root. We should search for all tsconfig.json and return all of them. If a build is trigger the task runner will run all of them + +Regarding activation: I have a similar problem in ESLint where I need to active the plugin to simply being able to listen to config changes. This is all I do in activate. In addition I listen to open event and if a JS files opens I start the ESLint server by hand. So basically I have an activate and a realActivate. We could do the same for TS and start the tsserver when we get a open event for a TS file in the listener registered in activate. ",2017-05-23 19:21:21 +486,"@@ -0,0 +1,111 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import * as crypto from 'crypto'; ++import * as fs from 'fs'; ++import * as path from 'path'; ++import Uri from 'vs/base/common/uri'; ++import { readdirSync } from 'vs/base/node/extfs'; ++import { IBackupWorkspacesFormat, IBackupMainService } from 'vs/platform/backup/common/backup'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++ ++export class BackupMainService implements IBackupMainService { ++ ++ public _serviceBrand: any; ++ ++ protected backupHome: string; ++ protected workspacesJsonPath: string; ++ ++ private workspacesJsonContent: IBackupWorkspacesFormat; ++ ++ constructor( ++ @IEnvironmentService environmentService: IEnvironmentService ++ ) { ++ this.backupHome = environmentService.backupHome; ++ this.workspacesJsonPath = environmentService.backupWorkspacesPath; ++ this.loadSync(); ++ } ++ ++ public getWorkspaceBackupPaths(): string[] { ++ return this.workspacesJsonContent.folderWorkspaces; ++ } ++ ++ public pushWorkspaceBackupPathsSync(workspaces: Uri[]): void { ++ workspaces.forEach(workspace => { ++ // Hot exit is disabled for empty workspaces ++ if (!workspace) { ++ return; ++ } ++ ++ if (this.workspacesJsonContent.folderWorkspaces.indexOf(workspace.fsPath) === -1) { ++ this.workspacesJsonContent.folderWorkspaces.push(workspace.fsPath); ++ } ++ }); ++ this.saveSync(); ++ } ++ ++ public removeWorkspaceBackupPathSync(workspace: Uri): void { ++ if (!this.workspacesJsonContent.folderWorkspaces) { ++ return; ++ } ++ const index = this.workspacesJsonContent.folderWorkspaces.indexOf(workspace.fsPath); ++ if (index === -1) { ++ return; ++ } ++ this.workspacesJsonContent.folderWorkspaces.splice(index, 1); ++ this.saveSync(); ++ } ++ ++ public getWorkspaceUntitledFileBackupsSync(workspace: Uri): string[] { ++ const untitledDir = path.join(this.getWorkspaceBackupDirectory(workspace), 'untitled'); ++ ++ // Allow sync here as it's only used in workbench initialization's critical path ++ try { ++ return readdirSync(untitledDir).map(file => path.join(untitledDir, file)); ++ } catch (ex) { ++ return []; ++ } ++ } ++ ++ public hasWorkspaceBackup(workspace: Uri): boolean { ++ return fs.existsSync(this.getWorkspaceBackupDirectory(workspace)); ++ } ++ ++ private getWorkspaceBackupDirectory(workspace: Uri): string { ++ const workspaceHash = crypto.createHash('md5').update(workspace.fsPath).digest('hex'); ++ return path.join(this.backupHome, workspaceHash); ++ } ++ ++ protected loadSync(): void { ++ try { ++ this.workspacesJsonContent = JSON.parse(fs.readFileSync(this.workspacesJsonPath, 'utf8').toString()); // invalid JSON or permission issue can happen here ++ } catch (error) { ++ this.workspacesJsonContent = Object.create(null); ++ } ++ ++ // Ensure folderWorkspaces is a string[] ++ if (this.workspacesJsonContent.folderWorkspaces) { ++ const fws = this.workspacesJsonContent.folderWorkspaces; ++ if (!Array.isArray(fws) || fws.some(f => typeof f !== 'string')) { ++ this.workspacesJsonContent = Object.create(null); ++ } ++ } ++ ++ if (!this.workspacesJsonContent.folderWorkspaces) { ++ this.workspacesJsonContent.folderWorkspaces = []; ++ } ++ } ++ ++ private saveSync(): void { ++ try { ++ // The user data directory must exist so only the Backup directory needs to be checked. ++ if (!fs.existsSync(this.backupHome)) { ++ fs.mkdirSync(this.backupHome); ++ } ++ fs.writeFileSync(this.workspacesJsonPath, JSON.stringify(this.workspacesJsonContent)); ++ } catch (ex) {","@Tyriar maybe add at least some logging here to be able to find out about issues more easily. +",2016-11-11 07:04:09 +415,"@@ -0,0 +1,115 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import nls = require('vs/nls'); ++import { TPromise } from 'vs/base/common/winjs.base'; ++import * as DOM from 'vs/base/browser/dom'; ++import { Builder, $ } from 'vs/base/browser/builder'; ++import { IWorkspace } from 'vs/platform/workspace/common/workspace'; ++import { CollapsibleViewletView } from 'vs/workbench/browser/viewlet'; ++import { IAction, IActionRunner } from 'vs/base/common/actions'; ++import { IMessageService } from 'vs/platform/message/common/message'; ++import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; ++import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; ++import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; ++import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; ++import { ITreeExplorerViewletService } from 'vs/workbench/parts/explorers/browser/treeExplorerViewletService'; ++import { ITree } from 'vs/base/parts/tree/browser/tree'; ++import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; ++import { TreeExplorerViewletState, TreeDataSource, TreeRenderer, TreeController } from 'vs/workbench/parts/explorers/browser/views/treeExplorerViewer'; ++import { RefreshViewExplorerAction } from 'vs/workbench/parts/explorers/browser/treeExplorerActions'; ++ ++export class TreeExplorerView extends CollapsibleViewletView { ++ private workspace: IWorkspace; ++ ++ constructor( ++ private viewletState: TreeExplorerViewletState, ++ private treeNodeProviderId: string, ++ actionRunner: IActionRunner, ++ headerSize: number, ++ @IMessageService messageService: IMessageService, ++ @IKeybindingService keybindingService: IKeybindingService, ++ @IContextMenuService contextMenuService: IContextMenuService, ++ @IWorkspaceContextService private contextService: IWorkspaceContextService, ++ @IInstantiationService private instantiationService: IInstantiationService, ++ @IWorkbenchEditorService private editorService: IWorkbenchEditorService, ++ @IEditorGroupService private editorGroupService: IEditorGroupService, ++ @ITreeExplorerViewletService private treeExplorerViewletService: ITreeExplorerViewletService ++ ) { ++ super(actionRunner, false, nls.localize('treeExplorerViewletTree', ""Tree Explorer Section""), messageService, keybindingService, contextMenuService, headerSize); ++ ++ this.workspace = contextService.getWorkspace(); ++ ++ this.create(); ++ } ++ ++ renderBody(container: HTMLElement): void { ++ this.treeContainer = super.renderViewTree(container); ++ DOM.addClass(this.treeContainer, 'tree-explorer-viewlet-tree-view'); ++ ++ this.tree = this.createViewer($(this.treeContainer)); ++ } ++ ++ createViewer(container: Builder): ITree { ++ const dataSource = this.instantiationService.createInstance(TreeDataSource, this.treeNodeProviderId); ++ const renderer = this.instantiationService.createInstance(TreeRenderer, this.viewletState, this.actionRunner, container.getHTMLElement()); ++ const controller = this.instantiationService.createInstance(TreeController, this.treeNodeProviderId); ++ const sorter = null; ++ const filter = null; ++ const dnd = null; ++ const accessibilityProvider = null; ++ ++ return new Tree(container.getHTMLElement(), { ++ dataSource, ++ renderer, ++ controller, ++ sorter, ++ filter, ++ dnd, ++ accessibilityProvider ++ }); ++ } ++ ++ getActions(): IAction[] { ++ const refresh = this.instantiationService.createInstance(RefreshViewExplorerAction, this); ++ return [refresh]; ++ } ++ ++ create(): TPromise { ++ return this.updateInput(); ++ } ++ ++ setVisible(visible: boolean): TPromise { ++ return super.setVisible(visible); ++ } ++ ++ updateInput(): TPromise { ++ if (this.treeExplorerViewletService.hasProvider(this.treeNodeProviderId)) { ++ return this.treeExplorerViewletService.provideRootNode(this.treeNodeProviderId).then(tree => { ++ this.tree.setInput(tree); ++ }); ++ } else {","else/indent is redundant +",2016-10-24 15:55:25 +652,"@@ -0,0 +1,118 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import { CodeLensProvider, CodeLens, CancellationToken, TextDocument, Range, Uri, Location, Position } from 'vscode'; ++import * as Proto from '../protocol'; ++import * as PConst from '../protocol.const'; ++ ++import { ITypescriptServiceClient } from '../typescriptService'; ++ ++import * as nls from 'vscode-nls'; ++let localize = nls.loadMessageBundle(); ++ ++ ++class ReferencesCodeLens extends CodeLens { ++ public document: Uri; ++ public file: string; ++ ++ constructor(document: Uri, file: string, range: Range) { ++ super(range); ++ this.document = document; ++ this.file = file; ++ } ++} ++ ++export default class TypeScriptReferencesCodeLensProvider implements CodeLensProvider { ++ private client: ITypescriptServiceClient; ++ ++ constructor(client: ITypescriptServiceClient) { ++ this.client = client; ++ } ++ ++ provideCodeLenses(document: TextDocument, token: CancellationToken): Promise { ++ const filepath = this.client.asAbsolutePath(document.uri); ++ if (!filepath) { ++ return Promise.resolve([]); ++ } ++ return this.client.execute('navtree', { file: filepath }, token).then(response => { ++ const tree = response.body; ++ const referenceableSpans: Range[] = []; ++ if (tree && tree.childItems) { ++ tree.childItems.forEach(item => this.extractReferenceableSymbols(item, referenceableSpans)); ++ } ++ return Promise.resolve(referenceableSpans.map(span => new ReferencesCodeLens(document.uri, filepath, span))); ++ }); ++ } ++ ++ resolveCodeLens(inputCodeLens: CodeLens, token: CancellationToken): Promise { ++ const codeLens = inputCodeLens as ReferencesCodeLens; ++ if (!codeLens.document) { ++ return Promise.reject(codeLens); ++ } ++ const args: Proto.FileLocationRequestArgs = { ++ file: codeLens.file, ++ line: codeLens.range.start.line + 1, ++ offset: codeLens.range.start.character + 1 ++ }; ++ return this.client.execute('references', args, token).then(response => { ++ if (response && response.body) { ++ const referenceCount = Math.max(0, response.body.refs.length - 1); ++ const locations = response.body.refs.map(reference => ++ new Location(codeLens.document, ++ new Range( ++ new Position(reference.start.line - 1, reference.start.offset - 1), ++ new Position(reference.end.line - 1, reference.end.offset - 1)))); ++ ++ codeLens.command = { ++ title: referenceCount + ' ' + (referenceCount === 1 ? localize('oneReferenceLabel', 'reference') : localize('manyReferenceLabel', 'references')), ++ command: 'editor.action.showReferences', ++ arguments: [codeLens.document, locations[0].range.start, locations.slice(1)] ++ }; ++ return Promise.resolve(codeLens); ++ } ++ return Promise.reject(codeLens); ++ }).catch(() => { ++ codeLens.command = { ++ title: localize('referenceErrorLabel', 'Could not determine references'), ++ command: '' ++ }; ++ return Promise.resolve(codeLens);","@jrieken What is the proper way to reject code lenses if resolving them fails? I tried using `Promise.reject`, but that leaves a bunch of ugly blank lines in the document: + +![screen shot 2017-01-05 at 7 17 23 pm](https://cloud.githubusercontent.com/assets/12821956/21706402/c4a051da-d37b-11e6-9f71-9016f251c61d.png) +",2017-01-06 03:19:16 +316,"@@ -0,0 +1,119 @@ ++/*---------------------------------------------------------------------------------------------","If this is a service it should move into vs/workbench/services ! +",2016-10-13 15:05:00 +317,"@@ -0,0 +1,119 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as path from 'path'; ++import * as crypto from 'crypto'; ++import * as fs from 'original-fs'; ++import * as arrays from 'vs/base/common/arrays'; ++import Uri from 'vs/base/common/uri'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { IBackupService } from 'vs/platform/backup/common/backup'; ++ ++interface IBackupFormat { ++ folderWorkspaces?: { ++ [workspacePath: string]: string[] ++ }; ++} ++ ++export class BackupService implements IBackupService { ++ ++ public _serviceBrand: any; ++ ++ private workspaceResource: Uri; ++ private workspacesJsonFilePath: string; ++ private fileContent: IBackupFormat; ++ ++ constructor( ++ @IEnvironmentService private environmentService: IEnvironmentService, ++ @IWorkspaceContextService contextService: IWorkspaceContextService ++ ) { ++ this.workspacesJsonFilePath = path.join(environmentService.userDataPath, 'Backups', 'workspaces.json');","Again this should be defined inside IEnvironmentService and not constructed +",2016-10-13 15:05:20 +318,"@@ -0,0 +1,119 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as path from 'path'; ++import * as crypto from 'crypto'; ++import * as fs from 'original-fs'; ++import * as arrays from 'vs/base/common/arrays'; ++import Uri from 'vs/base/common/uri'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { IBackupService } from 'vs/platform/backup/common/backup'; ++ ++interface IBackupFormat { ++ folderWorkspaces?: { ++ [workspacePath: string]: string[] ++ }; ++} ++ ++export class BackupService implements IBackupService { ++ ++ public _serviceBrand: any; ++ ++ private workspaceResource: Uri; ++ private workspacesJsonFilePath: string; ++ private fileContent: IBackupFormat; ++ ++ constructor( ++ @IEnvironmentService private environmentService: IEnvironmentService, ++ @IWorkspaceContextService contextService: IWorkspaceContextService ++ ) { ++ this.workspacesJsonFilePath = path.join(environmentService.userDataPath, 'Backups', 'workspaces.json'); ++ this.workspaceResource = contextService.getWorkspace().resource; ++ } ++ ++ public getBackupWorkspaces(): string[] { ++ this.load(); ++ return Object.keys(this.fileContent.folderWorkspaces || {}); ++ } ++ ++ public clearBackupWorkspaces(): void {","Again confused why this guy seems to be doing the same work as the backup service on the main side, plus some additional things. +",2016-10-13 15:06:03 +319,"@@ -0,0 +1,119 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as path from 'path'; ++import * as crypto from 'crypto'; ++import * as fs from 'original-fs'; ++import * as arrays from 'vs/base/common/arrays'; ++import Uri from 'vs/base/common/uri'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { IBackupService } from 'vs/platform/backup/common/backup'; ++ ++interface IBackupFormat { ++ folderWorkspaces?: { ++ [workspacePath: string]: string[] ++ }; ++} ++ ++export class BackupService implements IBackupService { ++ ++ public _serviceBrand: any; ++ ++ private workspaceResource: Uri; ++ private workspacesJsonFilePath: string; ++ private fileContent: IBackupFormat; ++ ++ constructor( ++ @IEnvironmentService private environmentService: IEnvironmentService, ++ @IWorkspaceContextService contextService: IWorkspaceContextService ++ ) { ++ this.workspacesJsonFilePath = path.join(environmentService.userDataPath, 'Backups', 'workspaces.json'); ++ this.workspaceResource = contextService.getWorkspace().resource; ++ } ++ ++ public getBackupWorkspaces(): string[] { ++ this.load(); ++ return Object.keys(this.fileContent.folderWorkspaces || {}); ++ } ++ ++ public clearBackupWorkspaces(): void { ++ this.fileContent = { ++ folderWorkspaces: {} ++ }; ++ this.save(); ++ } ++ ++ public removeWorkspace(workspace: string): void { ++ this.load(); ++ if (!this.fileContent.folderWorkspaces) { ++ return; ++ } ++ delete this.fileContent.folderWorkspaces[workspace]; ++ this.save(); ++ } ++ ++ public getBackupFiles(workspace: string): string[] { ++ this.load(); ++ return this.fileContent.folderWorkspaces[workspace] || []; ++ } ++ ++ public getBackupUntitledFiles(workspace: string): string[] { ++ const workspaceHash = crypto.createHash('md5').update(this.workspaceResource.fsPath).digest('hex');","What happens when the same file is edited in 2 windows? +",2016-10-13 15:06:33 +320,"@@ -0,0 +1,119 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as path from 'path'; ++import * as crypto from 'crypto'; ++import * as fs from 'original-fs'; ++import * as arrays from 'vs/base/common/arrays'; ++import Uri from 'vs/base/common/uri'; ++import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { IBackupService } from 'vs/platform/backup/common/backup'; ++ ++interface IBackupFormat { ++ folderWorkspaces?: { ++ [workspacePath: string]: string[] ++ }; ++} ++ ++export class BackupService implements IBackupService { ++ ++ public _serviceBrand: any; ++ ++ private workspaceResource: Uri; ++ private workspacesJsonFilePath: string; ++ private fileContent: IBackupFormat; ++ ++ constructor( ++ @IEnvironmentService private environmentService: IEnvironmentService, ++ @IWorkspaceContextService contextService: IWorkspaceContextService ++ ) { ++ this.workspacesJsonFilePath = path.join(environmentService.userDataPath, 'Backups', 'workspaces.json'); ++ this.workspaceResource = contextService.getWorkspace().resource; ++ } ++ ++ public getBackupWorkspaces(): string[] { ++ this.load(); ++ return Object.keys(this.fileContent.folderWorkspaces || {}); ++ } ++ ++ public clearBackupWorkspaces(): void { ++ this.fileContent = { ++ folderWorkspaces: {} ++ }; ++ this.save(); ++ } ++ ++ public removeWorkspace(workspace: string): void { ++ this.load(); ++ if (!this.fileContent.folderWorkspaces) { ++ return; ++ } ++ delete this.fileContent.folderWorkspaces[workspace]; ++ this.save(); ++ } ++ ++ public getBackupFiles(workspace: string): string[] { ++ this.load(); ++ return this.fileContent.folderWorkspaces[workspace] || []; ++ } ++ ++ public getBackupUntitledFiles(workspace: string): string[] { ++ const workspaceHash = crypto.createHash('md5').update(this.workspaceResource.fsPath).digest('hex'); ++ const untitledDir = path.join(this.environmentService.userDataPath, 'Backups', workspaceHash, 'untitled'); ++ try { ++ const untitledFiles = fs.readdirSync(untitledDir).map(file => path.join(untitledDir, file));","Red flag for sync fs API, we should avoid it by all means and use Promises instead if needed. +",2016-10-13 15:07:02 +14,"@@ -0,0 +1,12 @@ ++# EditorConfig is awesome: http://EditorConfig.org ++ ++# top-most EditorConfig file ++root = true ++ ++# Tab indentation (no size specified) ++[*] ++indent_style = tab ++ ++[{.travis.yml,npm-shrinkwrap.json}] ++indent_style = space ++indent_size = 2","indent must be 4 +",2015-11-24 09:12:49 +949,"@@ -0,0 +1,128 @@ ++{ ++ ""name"": ""merge-conflict"", ++ ""publisher"": ""vscode"", ++ ""displayName"": ""merge-conflict"", ++ ""description"": ""Merge Conflict"", ++ ""version"": ""0.7.0"", ++ ""aiKey"": ""AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217"", ++ ""enableProposedApi"": true,","Not needed, I believe. Remove the property to clarify.",2017-05-23 18:19:29 +947,"@@ -0,0 +1,128 @@ ++{ ++ ""name"": ""merge-conflict"", ++ ""publisher"": ""vscode"", ++ ""displayName"": ""merge-conflict"", ++ ""description"": ""Merge Conflict"", ++ ""version"": ""0.7.0"", ++ ""aiKey"": ""AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217"", ++ ""enableProposedApi"": true, ++ ""engines"": { ++ ""vscode"": ""^1.5.0"" ++ }, ++ ""categories"": [ ++ ""Other"" ++ ], ++ ""activationEvents"": [ ++ ""*"" ++ ], ++ ""main"": ""./out/extension"", ++ ""scripts"": { ++ ""compile"": ""gulp compile-extension:merge-conflict"", ++ ""watch"": ""gulp watch-extension:merge-conflict"" ++ }, ++ ""contributes"": { ++ ""commands"": [ ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.accept.all-incoming%"", ++ ""command"": ""merge-conflict.accept.all-incoming"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.accept.all-both%"", ++ ""command"": ""merge-conflict.accept.all-both"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.accept.current%"", ++ ""command"": ""merge-conflict.accept.current"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.accept.incoming%"", ++ ""command"": ""merge-conflict.accept.incoming"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""Accept selection"", ++ ""command"": ""merge-conflict.accept.selection"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.accept.both%"", ++ ""command"": ""merge-conflict.accept.both"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.next%"", ++ ""command"": ""merge-conflict.next"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.previous%"", ++ ""command"": ""merge-conflict.previous"" ++ }, ++ { ++ ""category"": ""%command.category%"", ++ ""title"": ""%command.compare%"", ++ ""command"": ""merge-conflict.compare"" ++ } ++ ], ++ ""keybindings"": [ ++ { ++ ""command"": ""merge-conflict.next"", ++ ""when"": ""editorTextFocus"", ++ ""key"": ""alt+m down"" ++ }, ++ { ++ ""command"": ""merge-conflict.previous"", ++ ""when"": ""editorTextFocus"", ++ ""key"": ""alt+m up"" ++ }, ++ { ++ ""command"": ""merge-conflict.accept.selection"", ++ ""when"": ""editorTextFocus"", ++ ""key"": ""alt+m enter"" ++ }, ++ { ++ ""command"": ""merge-conflict.accept.current"", ++ ""when"": ""editorTextFocus"", ++ ""key"": ""alt+m 1"" ++ }, ++ { ++ ""command"": ""merge-conflict.accept.incoming"", ++ ""when"": ""editorTextFocus"", ++ ""key"": ""alt+m 2"" ++ }, ++ { ++ ""command"": ""merge-conflict.accept.both"", ++ ""when"": ""editorTextFocus"", ++ ""key"": ""alt+m 3"" ++ } ++ ], ++ ""configuration"": { ++ ""title"": ""Merge Conflict"",",Extract to nls file for completeness.,2017-05-23 18:17:10 +116,"@@ -0,0 +1,129 @@ ++/*---------------------------------------------------------------------------------------------","This should also live in `electron-browser/`. +",2016-04-18 19:11:53 +51,"@@ -0,0 +1,13 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++.monaco-workbench > .panel > .content > .panel { ++ height: 100%; ++} ++ ++.monaco-workbench > .part.panel > .title { ++ display: block; ++ border-top: 1px solid #007ACC","@isidorn is this value not dynamic depending on debug, no workspace or workspace? I would check what the statusbar does to set this color. +",2016-01-19 11:07:45 +416,"@@ -0,0 +1,130 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { $, Builder } from 'vs/base/browser/builder'; ++import { ITree, IDataSource, IRenderer, IElementCallback } from 'vs/base/parts/tree/browser/tree'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ClickBehavior, DefaultController } from 'vs/base/parts/tree/browser/treeDefaults'; ++import { IMouseEvent } from 'vs/base/browser/mouseEvent'; ++import { IActionRunner } from 'vs/base/common/actions'; ++import { IActionProvider, ActionsRenderer } from 'vs/base/parts/tree/browser/actionsRenderer'; ++import { ContributableActionProvider } from 'vs/workbench/browser/actionBarRegistry'; ++import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; ++import { IExtensionService } from 'vs/platform/extensions/common/extensions'; ++import { IModeService } from 'vs/editor/common/services/modeService'; ++import { ITreeExplorerViewletService } from 'vs/workbench/parts/explorers/browser/treeExplorerViewletService'; ++import { IProgressService } from 'vs/platform/progress/common/progress'; ++ ++export class TreeDataSource implements IDataSource {","Fill in access modifiers +",2016-10-24 15:56:22 +417,"@@ -0,0 +1,130 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { $, Builder } from 'vs/base/browser/builder'; ++import { ITree, IDataSource, IRenderer, IElementCallback } from 'vs/base/parts/tree/browser/tree'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ClickBehavior, DefaultController } from 'vs/base/parts/tree/browser/treeDefaults'; ++import { IMouseEvent } from 'vs/base/browser/mouseEvent'; ++import { IActionRunner } from 'vs/base/common/actions'; ++import { IActionProvider, ActionsRenderer } from 'vs/base/parts/tree/browser/actionsRenderer'; ++import { ContributableActionProvider } from 'vs/workbench/browser/actionBarRegistry'; ++import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; ++import { IExtensionService } from 'vs/platform/extensions/common/extensions'; ++import { IModeService } from 'vs/editor/common/services/modeService'; ++import { ITreeExplorerViewletService } from 'vs/workbench/parts/explorers/browser/treeExplorerViewletService'; ++import { IProgressService } from 'vs/platform/progress/common/progress'; ++ ++export class TreeDataSource implements IDataSource { ++ ++ constructor( ++ private treeNodeProviderId: string, ++ @ITreeExplorerViewletService private treeExplorerViewletService: ITreeExplorerViewletService, ++ @IProgressService private progressService: IProgressService ++ ) { ++ ++ } ++ ++ getId(tree: ITree, node: InternalTreeExplorerNode): string { ++ return node.id.toString(); ++ } ++ ++ hasChildren(tree: ITree, node: InternalTreeExplorerNode): boolean { ++ return node.hasChildren; ++ } ++ ++ getChildren(tree: ITree, node: InternalTreeExplorerNode): TPromise { ++ const promise = this.treeExplorerViewletService.resolveChildren(this.treeNodeProviderId, node); ++ ++ this.progressService.showWhile(promise, 800);","Why 800? +",2016-10-24 15:57:30 +418,"@@ -0,0 +1,130 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { $, Builder } from 'vs/base/browser/builder'; ++import { ITree, IDataSource, IRenderer, IElementCallback } from 'vs/base/parts/tree/browser/tree'; ++import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel'; ++import { ClickBehavior, DefaultController } from 'vs/base/parts/tree/browser/treeDefaults'; ++import { IMouseEvent } from 'vs/base/browser/mouseEvent'; ++import { IActionRunner } from 'vs/base/common/actions'; ++import { IActionProvider, ActionsRenderer } from 'vs/base/parts/tree/browser/actionsRenderer'; ++import { ContributableActionProvider } from 'vs/workbench/browser/actionBarRegistry'; ++import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; ++import { IExtensionService } from 'vs/platform/extensions/common/extensions'; ++import { IModeService } from 'vs/editor/common/services/modeService'; ++import { ITreeExplorerViewletService } from 'vs/workbench/parts/explorers/browser/treeExplorerViewletService'; ++import { IProgressService } from 'vs/platform/progress/common/progress'; ++ ++export class TreeDataSource implements IDataSource { ++ ++ constructor( ++ private treeNodeProviderId: string, ++ @ITreeExplorerViewletService private treeExplorerViewletService: ITreeExplorerViewletService, ++ @IProgressService private progressService: IProgressService ++ ) { ++ ++ } ++ ++ getId(tree: ITree, node: InternalTreeExplorerNode): string { ++ return node.id.toString(); ++ } ++ ++ hasChildren(tree: ITree, node: InternalTreeExplorerNode): boolean { ++ return node.hasChildren; ++ } ++ ++ getChildren(tree: ITree, node: InternalTreeExplorerNode): TPromise { ++ const promise = this.treeExplorerViewletService.resolveChildren(this.treeNodeProviderId, node); ++ ++ this.progressService.showWhile(promise, 800); ++ ++ return promise; ++ } ++ ++ getParent(tree: ITree, node: InternalTreeExplorerNode): TPromise { ++ return TPromise.as(null); ++ } ++} ++ ++export class TreeRenderer extends ActionsRenderer implements IRenderer { ++ ++ constructor( ++ state: TreeExplorerViewletState, ++ actionRunner: IActionRunner, ++ private container: HTMLElement, ++ @IContextViewService private contextViewService: IContextViewService, ++ @IExtensionService private extensionService: IExtensionService, ++ @IModeService private modeService: IModeService ++ ) { ++ super({ ++ actionProvider: state.actionProvider, ++ actionRunner: actionRunner ++ }); ++ } ++ ++ getContentHeight(tree: ITree, element: any): number { ++ return 22;","Why 22? +",2016-10-24 15:57:48 +748,"@@ -0,0 +1,135 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as editorBrowser from 'vs/editor/browser/editorBrowser'; ++import { FastDomNode, createFastDomNode } from 'vs/base/browser/styleMutator'; ++import { Widget } from 'vs/base/browser/ui/widget'; ++import { IDisposable, dispose } from 'vs/base/common/lifecycle'; ++import { Configuration } from 'vs/editor/browser/config/configuration'; ++import { Position } from 'vs/editor/common/core/position'; ++import { IPosition, TextEditorCursorStyle, IConfigurationChangedEvent } from 'vs/editor/common/editorCommon'; ++ ++export class DragTargetHintWidget extends Widget implements editorBrowser.IContentWidget { ++ ++ static ID = 'editor.contrib.dragTargetHintWidget'; ++ protected _editor: editorBrowser.ICodeEditor; ++ protected _showAtPosition: Position; ++ private disposables: IDisposable[] = []; ++ private _cursorStyle: TextEditorCursorStyle; ++ private _lineHeight: number; ++ private _typicalHalfwidthCharacterWidth: number; ++ private readonly _domNode: FastDomNode;","Sorry for the compile error, use `FastDomNode`",2017-02-20 11:32:05 +749,"@@ -0,0 +1,135 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as editorBrowser from 'vs/editor/browser/editorBrowser'; ++import { FastDomNode, createFastDomNode } from 'vs/base/browser/styleMutator'; ++import { Widget } from 'vs/base/browser/ui/widget'; ++import { IDisposable, dispose } from 'vs/base/common/lifecycle'; ++import { Configuration } from 'vs/editor/browser/config/configuration'; ++import { Position } from 'vs/editor/common/core/position'; ++import { IPosition, TextEditorCursorStyle, IConfigurationChangedEvent } from 'vs/editor/common/editorCommon'; ++ ++export class DragTargetHintWidget extends Widget implements editorBrowser.IContentWidget { ++ ++ static ID = 'editor.contrib.dragTargetHintWidget'; ++ protected _editor: editorBrowser.ICodeEditor; ++ protected _showAtPosition: Position; ++ private disposables: IDisposable[] = []; ++ private _cursorStyle: TextEditorCursorStyle; ++ private _lineHeight: number; ++ private _typicalHalfwidthCharacterWidth: number; ++ private readonly _domNode: FastDomNode; ++ private _isVisible: boolean = false; ++ ++ protected get isVisible(): boolean { ++ return this._isVisible; ++ } ++ ++ protected set isVisible(value: boolean) { ++ this._isVisible = value; ++ } ++ ++ constructor(editor: editorBrowser.ICodeEditor) { ++ super(); ++ this._editor = editor; ++ ++ ++ // Create the dom node ++ this._domNode = createFastDomNode(document.createElement('div')); ++ this._domNode.setClassName('cursor secondary'); ++ this._domNode.setTop(0); ++ this._domNode.setLeft(0); ++ this._domNode.setAttribute('role', 'presentation'); ++ this._domNode.setAttribute('aria-hidden', 'true'); ++ this._domNode.setVisibility('hidden'); ++ this._editor.addContentWidget(this); ++ ++ this._cursorStyle = this._editor.getConfiguration().viewInfo.cursorStyle;","I don't like that we reuse here the cursor style and the cursor CSS. It makes it difficult to make changes in the CSS and e.g. it makes no sense to use a block cursor to paint the insertion point. + +IMHO the insertion point should always be rendered as a line, regardless of user settings. It is not a cursor, it is an insertion point. + +On top, I would render the insertion point in a distinct way than the cursor. I got very confused when I tried it out, it looks too much like a cursor, it should be orange or dashed or something special to let me know that it represents the drop point and is not some editor bug where a cursor is painted. + +It should also go away if the mouse is not sitting directly on text (mouseEvent.target !== CONTENT). If the drag is on top of a view zone, the margin, etc. there should be no drop. IMHO, only on top of content.",2017-02-20 11:35:12 +750,"@@ -0,0 +1,135 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as editorBrowser from 'vs/editor/browser/editorBrowser'; ++import { FastDomNode, createFastDomNode } from 'vs/base/browser/styleMutator'; ++import { Widget } from 'vs/base/browser/ui/widget'; ++import { IDisposable, dispose } from 'vs/base/common/lifecycle'; ++import { Configuration } from 'vs/editor/browser/config/configuration'; ++import { Position } from 'vs/editor/common/core/position'; ++import { IPosition, TextEditorCursorStyle, IConfigurationChangedEvent } from 'vs/editor/common/editorCommon'; ++ ++export class DragTargetHintWidget extends Widget implements editorBrowser.IContentWidget { ++ ++ static ID = 'editor.contrib.dragTargetHintWidget'; ++ protected _editor: editorBrowser.ICodeEditor; ++ protected _showAtPosition: Position; ++ private disposables: IDisposable[] = []; ++ private _cursorStyle: TextEditorCursorStyle; ++ private _lineHeight: number; ++ private _typicalHalfwidthCharacterWidth: number; ++ private readonly _domNode: FastDomNode; ++ private _isVisible: boolean = false; ++ ++ protected get isVisible(): boolean { ++ return this._isVisible; ++ } ++ ++ protected set isVisible(value: boolean) { ++ this._isVisible = value; ++ } ++ ++ constructor(editor: editorBrowser.ICodeEditor) { ++ super(); ++ this._editor = editor; ++ ++ ++ // Create the dom node ++ this._domNode = createFastDomNode(document.createElement('div')); ++ this._domNode.setClassName('cursor secondary'); ++ this._domNode.setTop(0); ++ this._domNode.setLeft(0); ++ this._domNode.setAttribute('role', 'presentation'); ++ this._domNode.setAttribute('aria-hidden', 'true'); ++ this._domNode.setVisibility('hidden'); ++ this._editor.addContentWidget(this); ++ ++ this._cursorStyle = this._editor.getConfiguration().viewInfo.cursorStyle; ++ this._lineHeight = this._editor.getConfiguration().lineHeight; ++ this._typicalHalfwidthCharacterWidth = this._editor.getConfiguration().fontInfo.typicalHalfwidthCharacterWidth; ++ ++ this._register(this._editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => { ++ if (e.fontInfo || e.viewInfo || e.lineHeight) { ++ this._typicalHalfwidthCharacterWidth = this._editor.getConfiguration().fontInfo.typicalHalfwidthCharacterWidth; ++ this._lineHeight = this._editor.getConfiguration().lineHeight; ++ this._cursorStyle = this._editor.getConfiguration().viewInfo.cursorStyle; ++ } ++ })); ++ ++ // render cursor after preparing the dom node and fetching data from config. ++ this.renderCursor(); ++ } ++ ++ public getId(): string { ++ return DragTargetHintWidget.ID; ++ } ++ ++ public getDomNode(): HTMLElement { ++ return this._domNode.domNode; ++ } ++ ++ public showAt(position: IPosition): void { ++ // Position has changed ++ this._showAtPosition = new Position(position.lineNumber, position.column); ++ this.show(); ++ this._editor.layoutContentWidget(this); ++ this._editor.render(); ++ } ++ ++ public show(): void { ++ if (!this._isVisible) { ++ this._domNode.setVisibility('inherit'); ++ this._isVisible = true; ++ } ++ this.renderCursor(); ++ } ++ ++ public hide(): void { ++ if (this._isVisible) { ++ this._domNode.setVisibility('hidden'); ++ this._isVisible = false; ++ this._editor.layoutContentWidget(this); ++ } ++ } ++ ++ public getPosition(): editorBrowser.IContentWidgetPosition { ++ if (this._isVisible) { ++ return { ++ position: this._showAtPosition, ++ preference: [ ++ editorBrowser.ContentWidgetPositionPreference.EXACT ++ ] ++ }; ++ } ++ return null; ++ } ++ ++ public dispose(): void { ++ this._editor.removeContentWidget(this); ++ this.disposables = dispose(this.disposables); ++ super.dispose(); ++ } ++ ++ private renderCursor() { ++ if (!this.isVisible) { ++ return; ++ } ++ ++ Configuration.applyFontInfo(this._domNode, this._editor.getConfiguration().fontInfo); ++ this._domNode.setHeight(this._lineHeight); ++ if (this._cursorStyle === TextEditorCursorStyle.Line) { ++ this._domNode.setWidth(1); ++ } else { ++ this._domNode.setWidth(this._typicalHalfwidthCharacterWidth); ++ } ++ ++ if (this._cursorStyle === TextEditorCursorStyle.Underline) {","I would use its own styles, doing this is nasty and to be honest, confused me a lot. I couldn't tell apart the cursor from the drop hint.",2017-02-20 11:35:48 +666,"@@ -0,0 +1,14 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as os from 'os'; ++import platform = require('vs/base/common/platform'); ++import processes = require('vs/base/node/processes'); ++ ++const powershellPath = `${ process.env.SystemRoot }/system32/WindowsPowerShell/v1.0/powershell.exe`;",I think `sysnative/` should be used on 64 bit machines? Please confirm @daviwil ,2017-01-13 06:53:21 +668,"@@ -0,0 +1,14 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as os from 'os'; ++import platform = require('vs/base/common/platform'); ++import processes = require('vs/base/node/processes'); ++ ++const powershellPath = `${ process.env.SystemRoot }/system32/WindowsPowerShell/v1.0/powershell.exe`; ++const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10;","I think you'd be better off getting the major version here as `os.release()` may return `x.y.z`? + +Something like this should be safe (if Node does indeed give that format): + +```js +parseInt(os.release().split('.')[0], 10) >= 10 +```",2017-01-13 06:57:17 +148,"@@ -0,0 +1,143 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import 'vs/css!./media/terminal.contribution'; ++import nls = require('vs/nls'); ++import product from 'vs/platform/product'; ++//import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; ++import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; ++import {registerSingleton} from 'vs/platform/instantiation/common/extensions'; ++import {IWorkbenchActionRegistry, Extensions as ActionExtensions} from 'vs/workbench/common/actionRegistry'; ++import {TerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminalService'; ++import {ToggleTerminalAction} from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; ++import {ITerminalService, TERMINAL_PANEL_ID, TERMINAL_DEFAULT_SHELL_UNIX_LIKE, TERMINAL_DEFAULT_SHELL_WINDOWS} from 'vs/workbench/parts/terminal/common/terminal'; ++import * as panel from 'vs/workbench/browser/panel'; ++import {Registry} from 'vs/platform/platform'; ++import {Extensions, IConfigurationRegistry} from 'vs/platform/configuration/common/configurationRegistry'; ++ ++// Only enable in the alpha channel until more stable ++if (product.quality === 'alpha') { ++ let configurationRegistry = Registry.as(Extensions.Configuration); ++ configurationRegistry.registerConfiguration({ ++ 'id': 'terminal', ++ 'order': 100, ++ 'title': nls.localize('integratedTerminalConfigurationTitle', ""(Experimental) Integrated terminal configuration""), ++ 'type': 'object', ++ 'properties': { ++ 'integratedTerminal.shell.unixLike': { ++ 'description': nls.localize('integratedTerminal.shell.unixLike', ""The path of the shell that the terminal uses on Linux and OS X.""), ++ 'type': 'string', ++ 'default': TERMINAL_DEFAULT_SHELL_UNIX_LIKE ++ }, ++ 'integratedTerminal.shell.windows': { ++ 'description': nls.localize('integratedTerminal.shell.windows', ""The path of the shell that the terminal uses on Windows.""), ++ 'type': 'string', ++ 'default': TERMINAL_DEFAULT_SHELL_WINDOWS ++ }, ++ 'integratedTerminal.fontFamily': { ++ 'description': nls.localize('integratedTerminal.fontFamily', ""The font family used by the terminal (CSS font-family format).""), ++ 'type': 'string', ++ 'default': 'Menlo, Monaco, Consolas, ""Droid Sans Mono"", ""Courier New"", monospace, ""Droid Sans Fallback""' ++ }, ++ 'integratedTerminal.ansiColors.black': { ++ 'description': nls.localize('integratedTerminal.ansiColors.black', ""Black color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#000000' ++ }, ++ 'integratedTerminal.ansiColors.red': { ++ 'description': nls.localize('integratedTerminal.ansiColors.red', ""Red color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#cd3131' ++ }, ++ 'integratedTerminal.ansiColors.green': { ++ 'description': nls.localize('integratedTerminal.ansiColors.green', ""Green color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#09885a' ++ }, ++ 'integratedTerminal.ansiColors.yellow': { ++ 'description': nls.localize('integratedTerminal.ansiColors.yellow', ""Yellow color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#e5e510' ++ }, ++ 'integratedTerminal.ansiColors.blue': { ++ 'description': nls.localize('integratedTerminal.ansiColors.blue', ""Blue color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#0451a5' ++ }, ++ 'integratedTerminal.ansiColors.magenta': { ++ 'description': nls.localize('integratedTerminal.ansiColors.magenta', ""Magenta color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#bc05bc' ++ }, ++ 'integratedTerminal.ansiColors.cyan': { ++ 'description': nls.localize('integratedTerminal.ansiColors.cyan', ""Cyan color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#0598bc' ++ }, ++ 'integratedTerminal.ansiColors.white': { ++ 'description': nls.localize('integratedTerminal.ansiColors.white', ""White color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#e5e5e5' ++ }, ++ 'integratedTerminal.ansiColors.brightBlack': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightBlack', ""Bright black color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#000000' ++ }, ++ 'integratedTerminal.ansiColors.brightRed': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightRed', ""Bright red color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#cd3131' ++ }, ++ 'integratedTerminal.ansiColors.brightGreen': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightGreen', ""Bright green color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#09885a' ++ }, ++ 'integratedTerminal.ansiColors.brightYellow': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightYellow', ""Bright yellow color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#e5e510' ++ }, ++ 'integratedTerminal.ansiColors.brightBlue': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightBlue', ""Bright blue color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#0451a5' ++ }, ++ 'integratedTerminal.ansiColors.brightMagenta': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightMagenta', ""Bright magenta color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#bc05bc' ++ }, ++ 'integratedTerminal.ansiColors.brightCyan': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightCyan', ""Bright cyan color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#0598bc' ++ }, ++ 'integratedTerminal.ansiColors.brightWhite': { ++ 'description': nls.localize('integratedTerminal.ansiColors.brightWhite', ""Bright white color for terminals that support ANSI escape sequences (format: #rrggbb)""), ++ 'type': 'string', ++ 'default': '#e5e5e5' ++ } ++ } ++ }); ++ ++ // Register Service ++ registerSingleton(ITerminalService, TerminalService); ++ ++ // Register Output Panel ++ (Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( ++ 'vs/workbench/parts/terminal/electron-browser/terminalPanel',","@Tyriar if you have an AMD entry point like this, it needs to be declared in our buildfile.js (see https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/buildfile.js#L34) +",2016-05-17 05:05:31 +140,"@@ -0,0 +1,145 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import termJs = require('term.js'); ++import fs = require('fs'); ++import {fork, Terminal} from 'pty.js'; ++import platform = require('vs/base/common/platform'); ++import {TPromise} from 'vs/base/common/winjs.base'; ++import {Builder, Dimension} from 'vs/base/browser/builder'; ++import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; ++import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; ++import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; ++import {ITerminalConfiguration, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; ++import {Panel} from 'vs/workbench/browser/panel'; ++import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl'; ++import {DomNodeScrollable} from 'vs/base/browser/ui/scrollbar/domNodeScrollable'; ++ ++const TERMINAL_CHAR_WIDTH = 8; ++const TERMINAL_CHAR_HEIGHT = 18; ++ ++export class TerminalPanel extends Panel { ++ ++ private ptyProcess: Terminal; ++ private parentDomElement: HTMLElement; ++ private terminal; ++ private terminalDomElement: HTMLDivElement; ++ ++ constructor( ++ @IConfigurationService private configurationService: IConfigurationService, ++ @ITelemetryService telemetryService: ITelemetryService, ++ @IWorkspaceContextService private contextService: IWorkspaceContextService ++ ) { ++ super(TERMINAL_PANEL_ID, telemetryService); ++ } ++ ++ public layout(dimension: Dimension): void { ++ let cols = Math.floor(this.parentDomElement.offsetWidth / TERMINAL_CHAR_WIDTH); ++ let rows = Math.floor(this.parentDomElement.offsetHeight / TERMINAL_CHAR_HEIGHT); ++ this.terminal.resize(cols, rows); ++ this.ptyProcess.resize(cols, rows); ++ } ++ ++ public create(parent: Builder): TPromise { ++ super.create(parent); ++ ++ this.parentDomElement = parent.getHTMLElement(); ++ this.createTerminal(); ++ ++ return TPromise.as(null); ++ } ++ ++ private createTerminal(): void { ++ this.parentDomElement.innerHTML = ''; ++ this.ptyProcess = fork(this.getShell(), [], { ++ name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm',","⚡ evil sync io inside the main thread. use callbacks/promises esp given your outer caller (`create`) allows you to do that +",2016-04-29 15:14:50 +141,"@@ -0,0 +1,145 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import termJs = require('term.js'); ++import fs = require('fs'); ++import {fork, Terminal} from 'pty.js'; ++import platform = require('vs/base/common/platform'); ++import {TPromise} from 'vs/base/common/winjs.base'; ++import {Builder, Dimension} from 'vs/base/browser/builder'; ++import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; ++import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; ++import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; ++import {ITerminalConfiguration, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; ++import {Panel} from 'vs/workbench/browser/panel'; ++import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl'; ++import {DomNodeScrollable} from 'vs/base/browser/ui/scrollbar/domNodeScrollable'; ++ ++const TERMINAL_CHAR_WIDTH = 8; ++const TERMINAL_CHAR_HEIGHT = 18; ++ ++export class TerminalPanel extends Panel { ++ ++ private ptyProcess: Terminal; ++ private parentDomElement: HTMLElement; ++ private terminal; ++ private terminalDomElement: HTMLDivElement; ++ ++ constructor( ++ @IConfigurationService private configurationService: IConfigurationService, ++ @ITelemetryService telemetryService: ITelemetryService, ++ @IWorkspaceContextService private contextService: IWorkspaceContextService ++ ) { ++ super(TERMINAL_PANEL_ID, telemetryService); ++ } ++ ++ public layout(dimension: Dimension): void { ++ let cols = Math.floor(this.parentDomElement.offsetWidth / TERMINAL_CHAR_WIDTH); ++ let rows = Math.floor(this.parentDomElement.offsetHeight / TERMINAL_CHAR_HEIGHT); ++ this.terminal.resize(cols, rows); ++ this.ptyProcess.resize(cols, rows); ++ } ++ ++ public create(parent: Builder): TPromise { ++ super.create(parent); ++ ++ this.parentDomElement = parent.getHTMLElement(); ++ this.createTerminal(); ++ ++ return TPromise.as(null); ++ } ++ ++ private createTerminal(): void { ++ this.parentDomElement.innerHTML = ''; ++ this.ptyProcess = fork(this.getShell(), [], { ++ name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', ++ cols: 80, ++ rows: 6, ++ cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.path : process.env.HOME ++ }); ++ this.terminalDomElement = document.createElement('div'); ++ this.parentDomElement.classList.add('integrated-terminal'); ++ let terminalScrollable = new DomNodeScrollable(this.terminalDomElement); ++ let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); ++ this.terminal = termJs({ ++ cursorBlink: false // term.js' blinking cursor breaks selection ++ }); ++ ++ this.ptyProcess.on('data', (data) => { ++ this.terminal.write(data); ++ }); ++ this.terminal.on('data', (data) => { ++ this.ptyProcess.write(data); ++ return false; ++ }); ++ this.ptyProcess.on('exit', (data) => { ++ this.terminal.destroy(); ++ // TODO: When multiple terminals are supported this should do something smarter. There is ++ // also a weird bug here at leasy on Ubuntu 15.10 where the new terminal text does not ++ // repaint correctly. ++ this.createTerminal(); ++ }); ++ this.parentDomElement.addEventListener('mousedown', (event) => { ++ // Drop selection and focus terminal on Linux to enable middle button paste when click ++ // occurs on the selection itself. ++ if (event.which === 2 && platform.isLinux) { ++ this.focusTerminal(true); ++ } ++ }); ++ this.parentDomElement.addEventListener('mouseup', (event) => { ++ if (event.which !== 3) { ++ this.focusTerminal(); ++ } ++ });",":zap: leakage! Use the `DOM.addDisposableListener` and other unbind/unlisten APIs, keep them, and implement `dispose` in the class +",2016-04-29 15:15:56 +142,"@@ -0,0 +1,145 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import termJs = require('term.js'); ++import fs = require('fs'); ++import {fork, Terminal} from 'pty.js'; ++import platform = require('vs/base/common/platform'); ++import {TPromise} from 'vs/base/common/winjs.base'; ++import {Builder, Dimension} from 'vs/base/browser/builder'; ++import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; ++import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; ++import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; ++import {ITerminalConfiguration, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; ++import {Panel} from 'vs/workbench/browser/panel'; ++import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl'; ++import {DomNodeScrollable} from 'vs/base/browser/ui/scrollbar/domNodeScrollable'; ++ ++const TERMINAL_CHAR_WIDTH = 8; ++const TERMINAL_CHAR_HEIGHT = 18; ++ ++export class TerminalPanel extends Panel { ++ ++ private ptyProcess: Terminal; ++ private parentDomElement: HTMLElement; ++ private terminal; ++ private terminalDomElement: HTMLDivElement; ++ ++ constructor( ++ @IConfigurationService private configurationService: IConfigurationService, ++ @ITelemetryService telemetryService: ITelemetryService, ++ @IWorkspaceContextService private contextService: IWorkspaceContextService ++ ) { ++ super(TERMINAL_PANEL_ID, telemetryService); ++ } ++ ++ public layout(dimension: Dimension): void { ++ let cols = Math.floor(this.parentDomElement.offsetWidth / TERMINAL_CHAR_WIDTH); ++ let rows = Math.floor(this.parentDomElement.offsetHeight / TERMINAL_CHAR_HEIGHT); ++ this.terminal.resize(cols, rows); ++ this.ptyProcess.resize(cols, rows); ++ } ++ ++ public create(parent: Builder): TPromise { ++ super.create(parent); ++ ++ this.parentDomElement = parent.getHTMLElement(); ++ this.createTerminal(); ++ ++ return TPromise.as(null); ++ } ++ ++ private createTerminal(): void { ++ this.parentDomElement.innerHTML = ''; ++ this.ptyProcess = fork(this.getShell(), [], { ++ name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', ++ cols: 80, ++ rows: 6, ++ cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.path : process.env.HOME ++ }); ++ this.terminalDomElement = document.createElement('div'); ++ this.parentDomElement.classList.add('integrated-terminal'); ++ let terminalScrollable = new DomNodeScrollable(this.terminalDomElement); ++ let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); ++ this.terminal = termJs({ ++ cursorBlink: false // term.js' blinking cursor breaks selection ++ }); ++ ++ this.ptyProcess.on('data', (data) => { ++ this.terminal.write(data); ++ }); ++ this.terminal.on('data', (data) => { ++ this.ptyProcess.write(data); ++ return false; ++ }); ++ this.ptyProcess.on('exit', (data) => { ++ this.terminal.destroy(); ++ // TODO: When multiple terminals are supported this should do something smarter. There is ++ // also a weird bug here at leasy on Ubuntu 15.10 where the new terminal text does not ++ // repaint correctly. ++ this.createTerminal(); ++ }); ++ this.parentDomElement.addEventListener('mousedown', (event) => { ++ // Drop selection and focus terminal on Linux to enable middle button paste when click ++ // occurs on the selection itself. ++ if (event.which === 2 && platform.isLinux) { ++ this.focusTerminal(true); ++ } ++ }); ++ this.parentDomElement.addEventListener('mouseup', (event) => { ++ if (event.which !== 3) { ++ this.focusTerminal(); ++ } ++ }); ++ ++ this.terminal.open(this.terminalDomElement); ++ this.parentDomElement.appendChild(terminalContainer.getDomNode()); ++ ++ let config = this.configurationService.getConfiguration(); ++ this.terminalDomElement.style.fontFamily = config.integratedTerminal.fontFamily; ++ this.terminal.colors = this.getTerminalColors();","unsure where/how that is configured but the terminal shows dark tho I use a light theme... +",2016-04-29 15:32:27 +461,"@@ -0,0 +1,147 @@ ++/*---------------------------------------------------------------------------------------------","@Tyriar I see warnings in this file. you gotta get your ghooks setup to prevent pushing files with warnings 👎 +",2016-11-09 07:05:49 +143,"@@ -0,0 +1,147 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++interface Entry { ++ next?: Entry; ++ prev?: Entry; ++ key: string; ++ value: T; ++} ++ ++/** ++ * A simple Map that optionally allows to set a limit of entries to store. Once the limit is hit, ++ * the cache will remove the entry that was last recently added. ++ */ ++export class LinkedMap { ++ protected map: { [key: string]: Entry }; ++ private head: Entry; ++ private tail: Entry; ++ private _size: number; ++ ++ constructor(private limit = Number.MAX_VALUE) { ++ this.map = Object.create(null); ++ this._size = 0; ++ } ++ ++ public get size(): number { ++ return this._size; ++ } ++ ++ public set(key: string, value: T): boolean { ++ if (this.map[key]) { ++ return false; // already present! ++ } ++ ++ const entry: Entry = { key, value }; ++ this.push(entry); ++ ++ if (this._size > this.limit) {","Soon you will end up removing a single item for each new item which is extra cost. Since the limit isn't so hard I would use a load factor, like if 3/4 of limit are reached remove so many items that you at 2/3 usage. That will make you remove less often. +",2016-05-02 10:11:59 +983,"@@ -0,0 +1,149 @@ ++# Auto-detect text files ++* text=auto",":memo: If the repository requires the use of a specific line ending by all users, it can be added to this line, and we can remove everything below except the *exceptions* to this case. However, the preferable case is to not require a specific line ending and instead allow it to be controlled by the user (or automated system) which checks out the code. For example, a build machine which validates line endings (I believe this is ""hygiene"" or something), could use the following configuration without being a noisy neighbor to all other contributors: + +``` +git config core.eol lf +```",2017-06-17 20:30:20 +981,"@@ -0,0 +1,149 @@ ++# Auto-detect text files ++* text=auto ++ ++# Some source files are edited with LF endings by everyone ++.editorconfig eol=lf ++.eslintrc eol=lf ++.gitignore eol=lf ++.mention-bot eol=lf ++COMMIT_EDITMSG eol=lf ++Dockerfile eol=lf ++git-rebase-todo eol=lf ++LICENSE eol=lf ++makefile eol=lf ++*.c eol=lf ++*.cc eol=lf ++*.clj eol=lf ++*.coffee eol=lf ++*.cpp eol=lf ++*.cs eol=lf ++*.cshtml eol=lf ++*.css eol=lf ++*.desktop eol=lf ++*.diff eol=lf ++*.fs eol=lf ++*.go eol=lf ++*.groovy eol=lf ++*.handlebars eol=lf ++*.hbs eol=lf ++*.hlsl eol=lf ++*.html eol=lf ++*.ini eol=lf ++*.java eol=lf ++*.js eol=lf ++*.json eol=lf ++*.jsx eol=lf ++*.less eol=lf ++*.lua eol=lf ++*.m eol=lf ++*.md eol=lf ++*.opts eol=lf ++*.php eol=lf ++*.pl eol=lf ++*.plist eol=lf ++*.pug eol=lf ++*.py eol=lf ++*.r eol=lf ++*.rb eol=lf ++*.recipe eol=lf ++*.rs eol=lf ++*.scss eol=lf ++*.shader eol=lf ++*.sql eol=lf ++*.svg eol=lf ++*.swift eol=lf ++*.template eol=lf ++*.tmLanguage eol=lf ++*.tmLanguage.base eol=lf ++*.tmTheme eol=lf ++*.ts eol=lf ++*.ts.disabled eol=lf ++*.tsx eol=lf ++*.txt eol=lf ++*.vb eol=lf ++*.vscodeignore eol=lf ++*.xml eol=lf ++*.xpm eol=lf ++*.yaml eol=lf ++*.yml eol=lf ++ ++# Some source files are edited with CRLF endings by everyone ++LICENSE.txt eol=crlf ++ThirdPartyNotices.txt eol=crlf ++*.isl eol=crlf ++*.iss eol=crlf ++*.jxs eol=crlf ++ ++# Some scripts require specific endings, others use specific in vscode ++*.bat eol=lf",":memo: Normally this would use `eol=crlf`, but the repository is not currently following this convention.",2017-06-17 20:20:18 +982,"@@ -0,0 +1,149 @@ ++# Auto-detect text files ++* text=auto ++ ++# Some source files are edited with LF endings by everyone ++.editorconfig eol=lf ++.eslintrc eol=lf ++.gitignore eol=lf ++.mention-bot eol=lf ++COMMIT_EDITMSG eol=lf ++Dockerfile eol=lf ++git-rebase-todo eol=lf ++LICENSE eol=lf ++makefile eol=lf ++*.c eol=lf ++*.cc eol=lf ++*.clj eol=lf ++*.coffee eol=lf ++*.cpp eol=lf ++*.cs eol=lf ++*.cshtml eol=lf ++*.css eol=lf ++*.desktop eol=lf ++*.diff eol=lf ++*.fs eol=lf ++*.go eol=lf ++*.groovy eol=lf ++*.handlebars eol=lf ++*.hbs eol=lf ++*.hlsl eol=lf ++*.html eol=lf ++*.ini eol=lf ++*.java eol=lf ++*.js eol=lf ++*.json eol=lf ++*.jsx eol=lf ++*.less eol=lf ++*.lua eol=lf ++*.m eol=lf ++*.md eol=lf ++*.opts eol=lf ++*.php eol=lf ++*.pl eol=lf ++*.plist eol=lf ++*.pug eol=lf ++*.py eol=lf ++*.r eol=lf ++*.rb eol=lf ++*.recipe eol=lf ++*.rs eol=lf ++*.scss eol=lf ++*.shader eol=lf ++*.sql eol=lf ++*.svg eol=lf ++*.swift eol=lf ++*.template eol=lf ++*.tmLanguage eol=lf ++*.tmLanguage.base eol=lf ++*.tmTheme eol=lf ++*.ts eol=lf ++*.ts.disabled eol=lf ++*.tsx eol=lf ++*.txt eol=lf ++*.vb eol=lf ++*.vscodeignore eol=lf ++*.xml eol=lf ++*.xpm eol=lf ++*.yaml eol=lf ++*.yml eol=lf ++ ++# Some source files are edited with CRLF endings by everyone ++LICENSE.txt eol=crlf ++ThirdPartyNotices.txt eol=crlf ++*.isl eol=crlf ++*.iss eol=crlf ++*.jxs eol=crlf ++ ++# Some scripts require specific endings, others use specific in vscode ++*.bat eol=lf ++*.cmd eol=crlf ++*.ps1 eol=lf",":memo: Normally this would use `eol=crlf`, but the repository is not currently following this convention.",2017-06-17 20:20:29 +693,"@@ -0,0 +1,156 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as strings from 'vs/base/common/strings'; ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { EditorInput, EditorModel, ITextEditorModel } from 'vs/workbench/common/editor'; ++import URI from 'vs/base/common/uri'; ++import { IReference } from 'vs/base/common/lifecycle'; ++import { telemetryURIDescriptor } from 'vs/platform/telemetry/common/telemetry'; ++import { ITextModelResolverService } from 'vs/editor/common/services/resolverService'; ++import { IFileService } from 'vs/platform/files/common/files'; ++import { marked } from 'vs/base/common/marked/marked'; ++import { WALK_THROUGH_SNIPPET_SCHEME } from 'vs/workbench/parts/walkThrough/node/walkThroughContentProvider'; ++ ++export class WalkThroughModel extends EditorModel { ++ ++ constructor( ++ private mainRef: IReference, ++ private snippetRefs: IReference[] ++ ) { ++ super(); ++ } ++ ++ get main() { ++ return this.mainRef.object; ++ } ++ ++ get snippets() { ++ return this.snippetRefs.map(snippet => snippet.object); ++ } ++ ++ dispose() { ++ this.snippetRefs.forEach(ref => ref.dispose()); ++ this.mainRef.dispose(); ++ super.dispose(); ++ } ++} ++ ++export class WalkThroughInput extends EditorInput { ++ ++ static ID: string = 'workbench.editors.walkThroughInput'; ++ ++ private promise: TPromise; ++ private resource: URI; ++ ++ private name: string; ++ private description: string; ++ ++ constructor( ++ name: string, ++ description: string, ++ resource: URI, ++ public readonly onReady: (container: HTMLElement) => void, ++ @IFileService private fileService: IFileService,",Unused,2017-01-19 06:02:00 +37,"@@ -0,0 +1,159 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import {TPromise} from 'vs/base/common/winjs.base'; ++import timer = require('vs/base/common/timer'); ++import uuid = require('vs/base/common/uuid'); ++import strings = require('vs/base/common/strings'); ++import {Registry} from 'vs/platform/platform'; ++import {IPanel} from 'vs/workbench/common/panel'; ++import {EventType as WorkbenchEventType, CompositeEvent} from 'vs/workbench/common/events'; ++import {CompositePart} from 'vs/workbench/browser/parts/compositePart'; ++import {Panel, PanelRegistry, Extensions as PanelExtensions} from 'vs/workbench/browser/panel'; ++import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; ++import {IPartService} from 'vs/workbench/services/part/common/partService'; ++import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'; ++import {IContextMenuService} from 'vs/platform/contextview/browser/contextView'; ++import {IEventService} from 'vs/platform/event/common/event'; ++import {IMessageService, Severity} from 'vs/platform/message/common/message'; ++import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; ++import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; ++ ++export class PanelPart extends CompositePart implements IPanelService { ++ ++ public static activePanelSettingsKey = 'workbench.panelpart.activepanelid'; ++ ++ public serviceId = IPanelService; ++ ++ private blockOpeningPanel: boolean; ++ private currentPanelOpenToken: string; ++ ++ constructor( ++ messageService: IMessageService, ++ storageService: IStorageService, ++ eventService: IEventService, ++ telemetryService: ITelemetryService, ++ contextMenuService: IContextMenuService, ++ partService: IPartService, ++ keybindingService: IKeybindingService, ++ id: string ++ ) { ++ super(messageService, storageService, eventService, telemetryService, contextMenuService, partService, keybindingService, ++ (Registry.as(PanelExtensions.Panels)), PanelPart.activePanelSettingsKey, id); ++ } ++ ++ public openPanel(id: string, focus?: boolean): TPromise { ++ if (this.blockOpeningPanel) {","@isidorn I would try to push this down to the compositePart because this seems like lots of duplicated code also in the panelPart. You would then also have just one onCompositeOpen event instead of onViewletOpen and onPanelOpen. +",2016-01-15 15:11:33 +38,"@@ -0,0 +1,159 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import {TPromise} from 'vs/base/common/winjs.base'; ++import timer = require('vs/base/common/timer'); ++import uuid = require('vs/base/common/uuid'); ++import strings = require('vs/base/common/strings'); ++import {Registry} from 'vs/platform/platform'; ++import {IPanel} from 'vs/workbench/common/panel'; ++import {EventType as WorkbenchEventType, CompositeEvent} from 'vs/workbench/common/events'; ++import {CompositePart} from 'vs/workbench/browser/parts/compositePart'; ++import {Panel, PanelRegistry, Extensions as PanelExtensions} from 'vs/workbench/browser/panel'; ++import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; ++import {IPartService} from 'vs/workbench/services/part/common/partService'; ++import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'; ++import {IContextMenuService} from 'vs/platform/contextview/browser/contextView'; ++import {IEventService} from 'vs/platform/event/common/event'; ++import {IMessageService, Severity} from 'vs/platform/message/common/message'; ++import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; ++import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; ++ ++export class PanelPart extends CompositePart implements IPanelService { ++ ++ public static activePanelSettingsKey = 'workbench.panelpart.activepanelid'; ++ ++ public serviceId = IPanelService; ++ ++ private blockOpeningPanel: boolean; ++ private currentPanelOpenToken: string; ++ ++ constructor( ++ messageService: IMessageService, ++ storageService: IStorageService, ++ eventService: IEventService, ++ telemetryService: ITelemetryService, ++ contextMenuService: IContextMenuService, ++ partService: IPartService, ++ keybindingService: IKeybindingService, ++ id: string ++ ) { ++ super(messageService, storageService, eventService, telemetryService, contextMenuService, partService, keybindingService, ++ (Registry.as(PanelExtensions.Panels)), PanelPart.activePanelSettingsKey, id); ++ } ++ ++ public openPanel(id: string, focus?: boolean): TPromise { ++ if (this.blockOpeningPanel) { ++ return TPromise.as(null); // Workaround against a potential race condition ++ } ++ ++ // First check if panel part is hidden and show if so ++ if (this.partService.isPanelPartHidden()) { ++ try { ++ this.blockOpeningPanel = true; ++ this.partService.setPanelPartHidden(false); ++ } finally { ++ this.blockOpeningPanel = false; ++ } ++ } ++ ++ // Check if panel already visible and just focus in that case ++ if (this.activePanel && this.activePanel.getId() === id) { ++ if (focus) { ++ this.activePanel.focus(); ++ } ++ ++ // Fullfill promise with panel that is being opened ++ return TPromise.as(this.activePanel); ++ } ++ ++ // Open ++ return this.doOpenPanel(id, focus); ++ } ++ ++ private doOpenPanel(id: string, focus?: boolean): TPromise { ++ let timerEvent = timer.start(timer.Topic.WORKBENCH, strings.format('Open Panel {0}', id.substr(id.lastIndexOf('.') + 1))); ++ ++ // Use a generated token to avoid race conditions from long running promises ++ let currentPanelOpenToken = uuid.generateUuid(); ++ this.currentPanelOpenToken = currentPanelOpenToken; ++ ++ // Emit Panel Opening Event ++ this.emit(WorkbenchEventType.PANEL_OPENING, new CompositeEvent(id)); ++ ++ // Hide current ++ let hidePromise: TPromise; ++ if (this.activePanel) { ++ hidePromise = this.hideActivePanel(); ++ } else { ++ hidePromise = TPromise.as(null); ++ } ++ ++ return hidePromise.then(() => { ++ ++ // Update Title ++ this.updateTitle(id); ++ ++ // Create panel ++ return this.createPanel(id, true).then((panel: Panel) => { ++ ++ // Check if another panel opened meanwhile and return in that case ++ if ((this.currentPanelOpenToken !== currentPanelOpenToken) || (this.activePanel && this.activePanel.getId() !== panel.getId())) { ++ timerEvent.stop(); ++ ++ return TPromise.as(null); ++ } ++ ++ // Check if panel already visible and just focus in that case ++ if (this.activePanel && this.activePanel.getId() === panel.getId()) { ++ if (focus) { ++ panel.focus(); ++ } ++ ++ timerEvent.stop(); ++ ++ // Fullfill promise with panel that is being opened ++ return TPromise.as(panel); ++ } ++ ++ // Show Panel and Focus ++ return this.showPanel(panel).then(() => { ++ if (focus) { ++ panel.focus(); ++ } ++ ++ timerEvent.stop(); ++ ++ // Fullfill promise with panel that is being opened ++ return panel; ++ }); ++ }); ++ }); ++ } ++ ++ private get activePanel(): IPanel {","All of this is super nice and shared. +",2016-01-15 15:11:53 +459,"@@ -0,0 +1,160 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as path from 'path'; ++import * as crypto from 'crypto'; ++import fs = require('fs'); ++import Uri from 'vs/base/common/uri'; ++import { readdirSync } from 'vs/base/node/extfs'; ++import { IBackupWorkspacesFormat } from 'vs/platform/backup/common/backup'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; ++ ++export const IBackupService = createDecorator('backupService'); ++ ++export interface IBackupService {","@Tyriar I suggest to move any service interfaces to `vs/platform`. If you need to distinguish between main and renderer you can call it `IBackupMainService`. +",2016-11-09 07:02:37 +460,"@@ -0,0 +1,160 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as path from 'path'; ++import * as crypto from 'crypto'; ++import fs = require('fs'); ++import Uri from 'vs/base/common/uri'; ++import { readdirSync } from 'vs/base/node/extfs'; ++import { IBackupWorkspacesFormat } from 'vs/platform/backup/common/backup'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; ++ ++export const IBackupService = createDecorator('backupService'); ++ ++export interface IBackupService { ++ _serviceBrand: any; ++ ++ /** ++ * Gets the set of active workspace backup paths being tracked for restoration. ++ * ++ * @return The set of active workspace backup paths being tracked for restoration. ++ */ ++ getWorkspaceBackupPathsSync(): string[]; ++ ++ /** ++ * Pushes workspace backup paths to be tracked for restoration. ++ * ++ * @param workspaces The workspaces to add. ++ */ ++ pushWorkspaceBackupPathsSync(workspaces: Uri[]): void; ++ ++ /** ++ * Removes a workspace backup path being tracked for restoration. ++ * ++ * @param workspace The workspace to remove. ++ */ ++ removeWorkspaceBackupPathSync(workspace: Uri): void; ++ ++ /** ++ * Gets the set of untitled file backups for a particular workspace. ++ * ++ * @param workspace The workspace to get the backups for. ++ * @return The absolute paths for all the untitled file _backups_. ++ */ ++ getWorkspaceUntitledFileBackupsSync(workspace: Uri): string[]; ++ ++ /** ++ * Gets whether the workspace has backups associated with it (ie. if the workspace backup ++ * directory exists). ++ * ++ * @param workspace The workspace to evaluate. ++ * @return Whether the workspace has backups. ++ */ ++ doesWorkspaceHaveBackups(workspace: Uri): boolean;","@Tyriar maybe better `hasWorkspaceBackup` or just `hasBackup` +",2016-11-09 07:04:46 +458,"@@ -0,0 +1,160 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as path from 'path'; ++import * as crypto from 'crypto'; ++import fs = require('fs'); ++import Uri from 'vs/base/common/uri'; ++import { readdirSync } from 'vs/base/node/extfs'; ++import { IBackupWorkspacesFormat } from 'vs/platform/backup/common/backup'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; ++ ++export const IBackupService = createDecorator('backupService'); ++ ++export interface IBackupService { ++ _serviceBrand: any; ++ ++ /** ++ * Gets the set of active workspace backup paths being tracked for restoration. ++ * ++ * @return The set of active workspace backup paths being tracked for restoration. ++ */ ++ getWorkspaceBackupPathsSync(): string[]; ++ ++ /** ++ * Pushes workspace backup paths to be tracked for restoration. ++ * ++ * @param workspaces The workspaces to add. ++ */ ++ pushWorkspaceBackupPathsSync(workspaces: Uri[]): void; ++ ++ /** ++ * Removes a workspace backup path being tracked for restoration. ++ * ++ * @param workspace The workspace to remove. ++ */ ++ removeWorkspaceBackupPathSync(workspace: Uri): void; ++ ++ /** ++ * Gets the set of untitled file backups for a particular workspace. ++ * ++ * @param workspace The workspace to get the backups for. ++ * @return The absolute paths for all the untitled file _backups_. ++ */ ++ getWorkspaceUntitledFileBackupsSync(workspace: Uri): string[]; ++ ++ /** ++ * Gets whether the workspace has backups associated with it (ie. if the workspace backup ++ * directory exists). ++ * ++ * @param workspace The workspace to evaluate. ++ * @return Whether the workspace has backups. ++ */ ++ doesWorkspaceHaveBackups(workspace: Uri): boolean; ++} ++ ++export class BackupService implements IBackupService { ++ ++ public _serviceBrand: any; ++ ++ protected backupHome: string; ++ protected workspacesJsonPath: string; ++ ++ private workspacesJsonContent: IBackupWorkspacesFormat; ++ ++ constructor( ++ @IEnvironmentService environmentService: IEnvironmentService ++ ) { ++ this.backupHome = environmentService.backupHome; ++ this.workspacesJsonPath = environmentService.backupWorkspacesPath; ++ } ++ ++ public getWorkspaceBackupPathsSync(): string[] { ++ this.loadSync();","@Tyriar why the `loadSync` on every method? The main process is a singleton so this should not be needed unless some other process writes to this file (which I would not expect). It should be sufficient to load once, keep in memory and save to disk on each write like we do in `storage.ts`. +",2016-11-09 07:01:26 +469,"@@ -0,0 +1,164 @@ ++/*---------------------------------------------------------------------------------------------","@Tyriar seeing again lots of warnings in this file +",2016-11-09 07:32:44 +580,"@@ -0,0 +1,167 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { IExpression } from 'vs/workbench/parts/debug/common/debug'; ++import { IDecorationOptions, IRange, IModel } from 'vs/editor/common/editorCommon'; ++import { createStringDictionary, IStringDictionary } from 'vs/base/common/collections'; ++import { StandardTokenType } from 'vs/editor/common/core/lineTokens'; ++ ++export const MAX_INLINE_VALUE_LENGTH = 50; // Max string length of each inline 'x = y' string. If exceeded ... is added ++export const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added ++export const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons ++export const MAX_TOKENIZATION_LINE_LEN = 500; // If line is too long, then inline values for the line are skipped ++export const ELLIPSES = '…'; ++// LanguageConfigurationRegistry.getWordDefinition() return regexes that allow spaces and punctuation characters for languages like python ++// Using that approach is not viable so we are using a simple regex to look for word tokens. ++export const WORD_REGEXP = /[\$\_A-Za-z][\$\_A-Za-z0-9]*/g;",For simplicity can we just use the regex \b word boundary character?,2016-12-05 15:12:54 +581,"@@ -0,0 +1,167 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { IExpression } from 'vs/workbench/parts/debug/common/debug'; ++import { IDecorationOptions, IRange, IModel } from 'vs/editor/common/editorCommon'; ++import { createStringDictionary, IStringDictionary } from 'vs/base/common/collections'; ++import { StandardTokenType } from 'vs/editor/common/core/lineTokens'; ++ ++export const MAX_INLINE_VALUE_LENGTH = 50; // Max string length of each inline 'x = y' string. If exceeded ... is added ++export const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added ++export const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons ++export const MAX_TOKENIZATION_LINE_LEN = 500; // If line is too long, then inline values for the line are skipped ++export const ELLIPSES = '…'; ++// LanguageConfigurationRegistry.getWordDefinition() return regexes that allow spaces and punctuation characters for languages like python ++// Using that approach is not viable so we are using a simple regex to look for word tokens. ++export const WORD_REGEXP = /[\$\_A-Za-z][\$\_A-Za-z0-9]*/g; ++ ++export function getNameValueMapFromScopeChildren(scopeExpressions: IExpression[][]): IStringDictionary {",This as a 2 dimensional array makes things overly complicated. Please make this one dimensional. Caller of this method could just merge mutliple expression arrays into one,2016-12-05 15:13:48 +579,"@@ -0,0 +1,167 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { IExpression } from 'vs/workbench/parts/debug/common/debug'; ++import { IDecorationOptions, IRange, IModel } from 'vs/editor/common/editorCommon'; ++import { createStringDictionary, IStringDictionary } from 'vs/base/common/collections'; ++import { StandardTokenType } from 'vs/editor/common/core/lineTokens'; ++ ++export const MAX_INLINE_VALUE_LENGTH = 50; // Max string length of each inline 'x = y' string. If exceeded ... is added ++export const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added ++export const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons ++export const MAX_TOKENIZATION_LINE_LEN = 500; // If line is too long, then inline values for the line are skipped ++export const ELLIPSES = '…'; ++// LanguageConfigurationRegistry.getWordDefinition() return regexes that allow spaces and punctuation characters for languages like python ++// Using that approach is not viable so we are using a simple regex to look for word tokens. ++export const WORD_REGEXP = /[\$\_A-Za-z][\$\_A-Za-z0-9]*/g; ++ ++export function getNameValueMapFromScopeChildren(scopeExpressions: IExpression[][]): IStringDictionary { ++ const nameValueMap = createStringDictionary(); ++ let valueCount = 0; ++ ++ for (let expressions of scopeExpressions) { ++ for (let expr of expressions) { ++ // Put ellipses in value if its too long. Preserve last char e.g ""longstr…"" or {a:true, b:true, …} ++ let value = expr.value; ++ if (value && value.length > MAX_INLINE_VALUE_LENGTH) { ++ value = value.substr(0, MAX_INLINE_VALUE_LENGTH - ELLIPSES.length) + ELLIPSES + value[value.length - 1]; ++ } ++ ++ nameValueMap[expr.name] = value; ++ ++ // Limit the size of map. Too large can have a perf impact ++ if (++valueCount >= MAX_NUM_INLINE_VALUES) { ++ return nameValueMap; ++ } ++ } ++ } ++ ++ return nameValueMap; ++} ++ ++export function getDecorators(nameValueMap: IStringDictionary, wordRangeMap: IStringDictionary, linesContent: string[]): IDecorationOptions[] { ++ const linesNames = createStringDictionary>(); ++ const names = Object.keys(nameValueMap); ++ const decorators: IDecorationOptions[] = []; ++ ++ // Compute unique set of names on each line ++ for (let name of names) { ++ const ranges = wordRangeMap[name]; ++ if (ranges) { ++ for (let range of ranges) { ++ const lineNum = range.startLineNumber; ++ if (!linesNames[lineNum]) { ++ linesNames[lineNum] = createStringDictionary(); ++ } ++ linesNames[lineNum][name] = true; ++ } ++ } ++ } ++ ++ // Compute decorators for each line ++ const lineNums = Object.keys(linesNames); ++ for (let lineNum of lineNums) { ++ const uniqueNames = Object.keys(linesNames[lineNum]); ++ const decorator = getDecoratorFromNames(parseInt(lineNum), uniqueNames, nameValueMap, linesContent); ++ decorators.push(decorator); ++ } ++ ++ return decorators; ++} ++ ++export function getDecoratorFromNames(lineNumber: number, names: string[], nameValueMap: IStringDictionary, linesContent: string[]): IDecorationOptions { ++ const margin = '10px'; ++ const backgroundColor = 'rgba(255,200,0,0.2)';",Adding css here is ugly. Is it possible to just add a css class and then style the decorations in debug.contribution.css?,2016-12-05 15:11:04 +577,"@@ -0,0 +1,167 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { IExpression } from 'vs/workbench/parts/debug/common/debug'; ++import { IDecorationOptions, IRange, IModel } from 'vs/editor/common/editorCommon'; ++import { createStringDictionary, IStringDictionary } from 'vs/base/common/collections'; ++import { StandardTokenType } from 'vs/editor/common/core/lineTokens'; ++ ++export const MAX_INLINE_VALUE_LENGTH = 50; // Max string length of each inline 'x = y' string. If exceeded ... is added ++export const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added ++export const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons ++export const MAX_TOKENIZATION_LINE_LEN = 500; // If line is too long, then inline values for the line are skipped ++export const ELLIPSES = '…'; ++// LanguageConfigurationRegistry.getWordDefinition() return regexes that allow spaces and punctuation characters for languages like python ++// Using that approach is not viable so we are using a simple regex to look for word tokens. ++export const WORD_REGEXP = /[\$\_A-Za-z][\$\_A-Za-z0-9]*/g; ++ ++export function getNameValueMapFromScopeChildren(scopeExpressions: IExpression[][]): IStringDictionary { ++ const nameValueMap = createStringDictionary(); ++ let valueCount = 0; ++ ++ for (let expressions of scopeExpressions) { ++ for (let expr of expressions) { ++ // Put ellipses in value if its too long. Preserve last char e.g ""longstr…"" or {a:true, b:true, …} ++ let value = expr.value; ++ if (value && value.length > MAX_INLINE_VALUE_LENGTH) { ++ value = value.substr(0, MAX_INLINE_VALUE_LENGTH - ELLIPSES.length) + ELLIPSES + value[value.length - 1]; ++ } ++ ++ nameValueMap[expr.name] = value; ++ ++ // Limit the size of map. Too large can have a perf impact ++ if (++valueCount >= MAX_NUM_INLINE_VALUES) { ++ return nameValueMap; ++ } ++ } ++ } ++ ++ return nameValueMap; ++} ++ ++export function getDecorators(nameValueMap: IStringDictionary, wordRangeMap: IStringDictionary, linesContent: string[]): IDecorationOptions[] { ++ const linesNames = createStringDictionary>(); ++ const names = Object.keys(nameValueMap); ++ const decorators: IDecorationOptions[] = []; ++ ++ // Compute unique set of names on each line ++ for (let name of names) { ++ const ranges = wordRangeMap[name]; ++ if (ranges) { ++ for (let range of ranges) { ++ const lineNum = range.startLineNumber; ++ if (!linesNames[lineNum]) { ++ linesNames[lineNum] = createStringDictionary(); ++ } ++ linesNames[lineNum][name] = true; ++ } ++ } ++ } ++ ++ // Compute decorators for each line ++ const lineNums = Object.keys(linesNames); ++ for (let lineNum of lineNums) { ++ const uniqueNames = Object.keys(linesNames[lineNum]); ++ const decorator = getDecoratorFromNames(parseInt(lineNum), uniqueNames, nameValueMap, linesContent); ++ decorators.push(decorator); ++ } ++ ++ return decorators; ++} ++ ++export function getDecoratorFromNames(lineNumber: number, names: string[], nameValueMap: IStringDictionary, linesContent: string[]): IDecorationOptions { ++ const margin = '10px'; ++ const backgroundColor = 'rgba(255,200,0,0.2)'; ++ const lightForegroundColor = 'rgba(0,0,0,0.5)'; ++ const darkForegroundColor = 'rgba(255,255,255,0.5)'; ++ const lineLength = linesContent[lineNumber - 1].length; ++ ++ // Wrap with 1em unicode space for readability ++ let contentText = '\u2003' + names.map(n => `${n} = ${nameValueMap[n]}`).join(', ') + '\u2003'; ++ ++ // If decoratorText is too long, trim and add ellipses. This could happen for minified files with everything on a single line ++ if (contentText.length > MAX_INLINE_DECORATOR_LENGTH) { ++ contentText = contentText.substr(0, MAX_INLINE_DECORATOR_LENGTH - ELLIPSES.length) + ELLIPSES; ++ } ++ ++ const decorator: IDecorationOptions = { ++ range: { ++ startLineNumber: lineNumber, ++ endLineNumber: lineNumber, ++ startColumn: lineLength, ++ endColumn: lineLength + 1 ++ }, ++ renderOptions: { ++ dark: { ++ after: { ++ contentText, ++ backgroundColor, ++ color: darkForegroundColor, ++ margin ++ } ++ }, ++ light: { ++ after: { ++ contentText, ++ backgroundColor, ++ color: lightForegroundColor, ++ margin ++ } ++ } ++ } ++ }; ++ ++ return decorator; ++} ++ ++export function getEditorWordRangeMap(editorModel: IModel): IStringDictionary { ++ const wordRangeMap = createStringDictionary(); ++ const linesContent = editorModel.getLinesContent(); ++ ++ // For every word in every line, map its ranges for fast lookup ++ for (let i = 0, len = linesContent.length; i < len; ++i) { ++ const lineContent = linesContent[i]; ++ ++ // If line is too long then skip the line ++ if (lineContent.length > MAX_TOKENIZATION_LINE_LEN) { ++ continue; ++ } ++ ++ const lineTokens = editorModel.getLineTokens(i + 1); // lineNumbers are 1 based ++ ++ for (let j = 0, len = lineTokens.getTokenCount(); j < len; ++j) { ++ let startOffset = lineTokens.getTokenStartOffset(j); ++ let endOffset = lineTokens.getTokenEndOffset(j); ++ const tokenStr = lineContent.substring(startOffset, endOffset); ++ ++ // Token is a word and not a comment ++ if (lineTokens.getStandardTokenType(j) !== StandardTokenType.Comment) {",Great that you are using getStandardTokenType() since that is the new recommanded way of handling tokens,2016-12-05 15:04:38 +184,"@@ -0,0 +1,170 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as vscode from 'vscode'; ++import * as path from 'path'; ++import { ExtensionContext, TextDocumentContentProvider, EventEmitter, Event, Uri, ViewColumn } from ""vscode""; ++ ++const hljs = require('highlight.js'); ++const mdnh = require('markdown-it-named-headers'); ++const md = require('markdown-it')({ ++ html: true, ++ highlight: function (str, lang) { ++ if (lang && hljs.getLanguage(lang)) { ++ try { ++ return `
${hljs.highlight(lang, str, true).value}
`; ++ } catch (error) { } ++ } ++ return `
${md.utils.escapeHtml(str)}
`; ++ } ++}).use(mdnh, {});","If you don't mind me asking. As it is coded here, anytime a member wants to add a plugin to markdown-it, it seems they will have to: +1. `Npm install markdown-it-plugin --savedev` in extensions folder +2. Require package here and add package to `.use(...)` + +This seems fine to me, but I believe that also means I would have to do this _every_ time that extension is updated. I don't know of a good solution, but one solution I thought of is to allow for developers to create a ""skeleton"" package that simply exposes and api to the markdown extension that says use this. So people will be able to install a package, say: `vscode-markdown-it-katex` for math support which has a dependency on this package and it should just work. Not an ideal solution, but maybe there is a better one? I could open this as a feature request if you would like to defer this until another cycle. Or possibly a pull request later on. +",2016-06-14 18:32:11 +185,"@@ -0,0 +1,170 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import * as vscode from 'vscode'; ++import * as path from 'path'; ++import { ExtensionContext, TextDocumentContentProvider, EventEmitter, Event, Uri, ViewColumn } from ""vscode""; ++ ++const hljs = require('highlight.js'); ++const mdnh = require('markdown-it-named-headers'); ++const md = require('markdown-it')({ ++ html: true, ++ highlight: function (str, lang) { ++ if (lang && hljs.getLanguage(lang)) { ++ try { ++ return `
${hljs.highlight(lang, str, true).value}
`; ++ } catch (error) { } ++ } ++ return `
${md.utils.escapeHtml(str)}
`; ++ } ++}).use(mdnh, {}); ++ ++export function activate(context: ExtensionContext) { ++ let provider = new MDDocumentContentProvider(context); ++ let registration = vscode.workspace.registerTextDocumentContentProvider('markdown', provider); ++ ++ let d1 = vscode.commands.registerCommand('extension.previewMarkdown', () => openPreview()); ++ let d2 = vscode.commands.registerCommand('extension.previewMarkdownSide', () => openPreview(true)); ++ ++ context.subscriptions.push(d1, d2, registration); ++ ++ vscode.workspace.onDidSaveTextDocument(document => { ++ if (isMarkdownFile(document)) { ++ const uri = getMarkdownUri(document); ++ provider.update(uri); ++ } ++ }); ++ ++ vscode.workspace.onDidChangeTextDocument(event => { ++ if (isMarkdownFile(event.document)) { ++ const uri = getMarkdownUri(event.document); ++ provider.update(uri); ++ ++ } ++ }); ++ ++ vscode.workspace.onDidChangeConfiguration(() => { ++ vscode.workspace.textDocuments.forEach((document) => { ++ if (isMarkdownFile) { ++ provider.update(document.uri); ++ } ++ }); ++ }); ++} ++ ++function isMarkdownFile(document: vscode.TextDocument) { ++ return document.languageId === 'markdown' ++ && document.uri.scheme !== 'markdown'; // prevent processing of own documents ++} ++ ++function getMarkdownUri(document: vscode.TextDocument) { ++ return document.uri.with({ scheme: 'markdown', query: document.uri.toString() }); ++} ++ ++function openPreview(sideBySide?: boolean): void { ++ const activeEditor = vscode.window.activeTextEditor; ++ if (!activeEditor) { ++ vscode.commands.executeCommand('workbench.action.navigateBack'); ++ return; ++ } ++ ++ let markdownPreviewUri = getMarkdownUri(activeEditor.document); ++ vscode.commands.executeCommand('vscode.previewHtml', ++ markdownPreviewUri, ++ getViewColumn(sideBySide), ++ `Preview '${path.basename(activeEditor.document.fileName)}'`); ++} ++ ++function getViewColumn(sideBySide): ViewColumn { ++ const active = vscode.window.activeTextEditor; ++ if (!active) { ++ return ViewColumn.One; ++ } ++ ++ if (!sideBySide) { ++ return active.viewColumn; ++ } ++ ++ switch (active.viewColumn) { ++ case ViewColumn.One: ++ return ViewColumn.Two; ++ case ViewColumn.Two: ++ return ViewColumn.Three; ++ } ++ ++ return active.viewColumn; ++} ++ ++ ++class MDDocumentContentProvider implements TextDocumentContentProvider { ++ private _context: ExtensionContext; ++ private _onDidChange = new EventEmitter(); ++ ++ constructor(context: ExtensionContext) { ++ this._context = context; ++ } ++ ++ private getMediaPath(mediaFile) { ++ return this._context.asAbsolutePath(path.join('media', mediaFile)); ++ } ++ ++ private fixHref(resource: Uri, href: string) { ++ if (href) { ++ // Return early if href is already a URL ++ if (Uri.parse(href).scheme) { ++ return href; ++ } ++ // Otherwise convert to a file URI by joining the href with the resource location ++ return Uri.file(path.join(path.dirname(resource.fsPath), href)).toString(); ++ } ++ return href; ++ } ++ ++ private computeCustomStyleSheetIncludes(uri: Uri): string[] { ++ const styles = vscode.workspace.getConfiguration('markdown')['styles']; ++ if (styles && Array.isArray(styles)) { ++ return styles.map((style) => { ++ return ``; ++ }); ++ } ++ return []; ++ } ++ ++ public provideTextDocumentContent(uri: Uri): Thenable { ++ ++ return vscode.workspace.openTextDocument(Uri.parse(uri.query)).then(document => { ++ const head = [].concat( ++ '', ++ '', ++ '', ++ '', ++ ``, ++ ``, ++ this.computeCustomStyleSheetIncludes(uri), ++ '', ++ '' ++ ).join('\n'); ++ ++ const body = md.render(document.getText()); ++ ++ const tail = [ ++ '', ++ '' ++ ].join('\n'); ++ ++ return head + body + tail; ++ }); ++ } ++ ++ get onDidChange(): Event { ++ return this._onDidChange.event; ++ } ++ ++ public update(uri: Uri) { ++ this._onDidChange.fire(uri);","Have you considered a timout here? Spamming markdown-it may not always be a good idea. This is more true when you add more plugins like `highlight` and when I was testing for math support `katex`. I simply did something like: + +``` + if (!this._waiting) { + this._waiting = true; + setTimeout(() => { + this._waiting = false; + this._onDidChange.fire(uri); + }, 300); + } +``` + +The timeout should probably be modifiable by the user, maybe even default to 0 with a note that for those who may experience problems. +",2016-06-14 18:42:38 +113,"@@ -0,0 +1,18 @@ ++/*---------------------------------------------------------------------------------------------","This file should live in `src/vs/workbench/parts/execution/common/electron-browser/terminal.ts` as it's not usable in a browser. Check out [this wiki page](https://github.com/Microsoft/vscode/blob/master/wiki/contributing/code-organization.md#target-environments) for more information on code organization, basically things in common/ and browser/ need to work both in vscode (under node) and in monaco (on a browser). +",2016-04-18 16:40:27 +671,"@@ -0,0 +1,18 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as os from 'os'; ++import platform = require('vs/base/common/platform'); ++import processes = require('vs/base/node/processes'); ++ ++const powerShellExePath = ++ !process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432')",@daviwil so this is an env variable only available on 64 bit Windows? Would it be better to check `process.arch` instead?,2017-01-14 02:18:24 +111,"@@ -0,0 +1,18 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++import fs = require('fs'); ++import env = require('vs/base/common/platform');","`env` -> `platform`, I think the instances where this is `env` are older ones that weren't cleaned up +",2016-04-18 16:37:36 +112,"@@ -0,0 +1,18 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++import fs = require('fs'); ++import env = require('vs/base/common/platform'); ++ ++export let defaultLinuxTerm = 'x-terminal-emulator'; ++ ++// if we're not on debian and using gnome then ++// set default to gnome-terminal ++if (env.isLinux ++ && fs.existsSync('/etc/debian_version') === false ++ && process.env.DESKTOP_SESSION === 'gnome') { ++ defaultLinuxTerm = 'gnome-terminal'; ++} ++ ++export const defaultWindowsTerm = 'cmd';","Rename this and `defaultLinuxTerm` as `ALL_CAPS_NAMING`. +",2016-04-18 16:37:37 +773,"@@ -0,0 +1,184 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import { Position, Selection, Range, CompletionItemProvider, CompletionItemKind, TextDocument, CancellationToken, CompletionItem, window, commands, Uri, ProviderResult, TextEditor } from 'vscode'; ++ ++import { ITypescriptServiceClient } from '../typescriptService'; ++import { FileLocationRequestArgs, DocCommandTemplateResponse } from '../protocol'; ++ ++import * as nls from 'vscode-nls'; ++const localize = nls.loadMessageBundle(); ++ ++const tryCompleteJsDocCommand = '_typeScript.tryCompleteJsDoc'; ++ ++ ++class JsDocCompletionItem extends CompletionItem { ++ constructor(file: Uri, position: Position) { ++ super('/** @param */', CompletionItemKind.Snippet); ++ this.detail = localize('typescript.jsDocCompletionItem.detail', 'Complete JSDoc comment'); ++ this.insertText = ''; ++ this.command = { ++ title: 'Try Complete Js Doc', ++ command: tryCompleteJsDocCommand, ++ arguments: [file, position] ++ };","You are on very thin ice with this... It is really not recommended to modify the document using [`CompletionItem#command`](https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.d.ts#L2510). Cursor state and undo stack might be get confused by this. + +@mjbvz Any reason why you don't use [`CompletionItem#insertText`](https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.d.ts#L2466) and [`CompletionItem#range`](https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.d.ts#L2477). You could create a range that encloses the current, partial doc comment, and replace that with the new text",2017-02-22 15:07:44 +774,"@@ -0,0 +1,184 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import { Position, Selection, Range, CompletionItemProvider, CompletionItemKind, TextDocument, CancellationToken, CompletionItem, window, commands, Uri, ProviderResult, TextEditor } from 'vscode'; ++ ++import { ITypescriptServiceClient } from '../typescriptService'; ++import { FileLocationRequestArgs, DocCommandTemplateResponse } from '../protocol'; ++ ++import * as nls from 'vscode-nls'; ++const localize = nls.loadMessageBundle(); ++ ++const tryCompleteJsDocCommand = '_typeScript.tryCompleteJsDoc'; ++ ++ ++class JsDocCompletionItem extends CompletionItem { ++ constructor(file: Uri, position: Position) { ++ super('/** @param */', CompletionItemKind.Snippet); ++ this.detail = localize('typescript.jsDocCompletionItem.detail', 'Complete JSDoc comment'); ++ this.insertText = ''; ++ this.command = { ++ title: 'Try Complete Js Doc', ++ command: tryCompleteJsDocCommand, ++ arguments: [file, position] ++ }; ++ } ++} ++ ++export default class JsDocCompletionHelper implements CompletionItemProvider { ++ ++ constructor( ++ private client: ITypescriptServiceClient, ++ ) { ++ window.onDidChangeTextEditorSelection(e => { ++ if (e.textEditor.document.languageId !== 'typescript' ++ && e.textEditor.document.languageId !== 'typescriptreact' ++ && e.textEditor.document.languageId !== 'javascript' ++ && e.textEditor.document.languageId !== 'javascriptreact' ++ ) { ++ return; ++ } ++ ++ const selection = e.selections[0]; ++ if (!selection.start.isEqual(selection.end)) { ++ return; ++ } ++ if (this.shouldAutoShowJsDocSuggestion(e.textEditor.document, selection.start)) { ++ return commands.executeCommand('editor.action.triggerSuggest');","We have all sorts of commands and settings to trigger suggestions, for instance 24x7 or provider-specific trigger characters. This is somewhat backwards and I wonder why that is needed? This provider could for instance use `*` as trigger character to complete `/**` sequences. It's also being continuously asked for suggestion because the default config is `editor.quickSuggestion: true`. The idea is not trigger yourself but to know when to return something ",2017-02-22 15:10:58 +775,"@@ -0,0 +1,184 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import { Position, Selection, Range, CompletionItemProvider, CompletionItemKind, TextDocument, CancellationToken, CompletionItem, window, commands, Uri, ProviderResult, TextEditor } from 'vscode'; ++ ++import { ITypescriptServiceClient } from '../typescriptService'; ++import { FileLocationRequestArgs, DocCommandTemplateResponse } from '../protocol'; ++ ++import * as nls from 'vscode-nls'; ++const localize = nls.loadMessageBundle(); ++ ++const tryCompleteJsDocCommand = '_typeScript.tryCompleteJsDoc'; ++ ++ ++class JsDocCompletionItem extends CompletionItem { ++ constructor(file: Uri, position: Position) { ++ super('/** @param */', CompletionItemKind.Snippet); ++ this.detail = localize('typescript.jsDocCompletionItem.detail', 'Complete JSDoc comment'); ++ this.insertText = ''; ++ this.command = { ++ title: 'Try Complete Js Doc', ++ command: tryCompleteJsDocCommand, ++ arguments: [file, position] ++ }; ++ } ++} ++ ++export default class JsDocCompletionHelper implements CompletionItemProvider { ++ ++ constructor( ++ private client: ITypescriptServiceClient, ++ ) { ++ window.onDidChangeTextEditorSelection(e => { ++ if (e.textEditor.document.languageId !== 'typescript' ++ && e.textEditor.document.languageId !== 'typescriptreact' ++ && e.textEditor.document.languageId !== 'javascript' ++ && e.textEditor.document.languageId !== 'javascriptreact' ++ ) { ++ return; ++ } ++ ++ const selection = e.selections[0]; ++ if (!selection.start.isEqual(selection.end)) { ++ return; ++ } ++ if (this.shouldAutoShowJsDocSuggestion(e.textEditor.document, selection.start)) { ++ return commands.executeCommand('editor.action.triggerSuggest'); ++ } ++ return; ++ }); ++ ++ commands.registerCommand( ++ tryCompleteJsDocCommand, ++ (file: Uri, position: Position) => this.tryCompleteJsDoc(file, position)); ++ } ++ ++ public provideCompletionItems(document: TextDocument, position: Position, _token: CancellationToken): ProviderResult { ++ const file = this.client.normalizePath(document.uri); ++ if (file) { ++ return [new JsDocCompletionItem(document.uri, position)];","Unconditionally returning a completion is causing https://github.com/Microsoft/vscode/issues/21147. Expect this method to be called 'randomly' (see above). Because you cannot control when that happens, the function must check the document/postion for a valid jsdoc-insertion locations and return something falsy else",2017-02-22 15:11:46 +776,"@@ -0,0 +1,184 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import { Position, Selection, Range, CompletionItemProvider, CompletionItemKind, TextDocument, CancellationToken, CompletionItem, window, commands, Uri, ProviderResult, TextEditor } from 'vscode'; ++ ++import { ITypescriptServiceClient } from '../typescriptService'; ++import { FileLocationRequestArgs, DocCommandTemplateResponse } from '../protocol'; ++ ++import * as nls from 'vscode-nls'; ++const localize = nls.loadMessageBundle(); ++ ++const tryCompleteJsDocCommand = '_typeScript.tryCompleteJsDoc'; ++ ++ ++class JsDocCompletionItem extends CompletionItem { ++ constructor(file: Uri, position: Position) { ++ super('/** @param */', CompletionItemKind.Snippet); ++ this.detail = localize('typescript.jsDocCompletionItem.detail', 'Complete JSDoc comment'); ++ this.insertText = ''; ++ this.command = { ++ title: 'Try Complete Js Doc', ++ command: tryCompleteJsDocCommand, ++ arguments: [file, position] ++ }; ++ } ++} ++ ++export default class JsDocCompletionHelper implements CompletionItemProvider { ++ ++ constructor( ++ private client: ITypescriptServiceClient, ++ ) { ++ window.onDidChangeTextEditorSelection(e => { ++ if (e.textEditor.document.languageId !== 'typescript' ++ && e.textEditor.document.languageId !== 'typescriptreact' ++ && e.textEditor.document.languageId !== 'javascript' ++ && e.textEditor.document.languageId !== 'javascriptreact' ++ ) { ++ return; ++ } ++ ++ const selection = e.selections[0]; ++ if (!selection.start.isEqual(selection.end)) { ++ return; ++ } ++ if (this.shouldAutoShowJsDocSuggestion(e.textEditor.document, selection.start)) { ++ return commands.executeCommand('editor.action.triggerSuggest'); ++ } ++ return; ++ }); ++ ++ commands.registerCommand( ++ tryCompleteJsDocCommand, ++ (file: Uri, position: Position) => this.tryCompleteJsDoc(file, position)); ++ } ++ ++ public provideCompletionItems(document: TextDocument, position: Position, _token: CancellationToken): ProviderResult { ++ const file = this.client.normalizePath(document.uri); ++ if (file) { ++ return [new JsDocCompletionItem(document.uri, position)]; ++ } ++ return []; ++ } ++ ++ public resolveCompletionItem(item: CompletionItem, _token: CancellationToken) { ++ return item; ++ } ++ ++ private shouldAutoShowJsDocSuggestion(document: TextDocument, position: Position): boolean { ++ const line = document.lineAt(position.line).text; ++ ++ // Ensure line starts with '/**' then cursor ++ const prefix = line.slice(0, position.character).match(/^\s*(\/\*\*+)\s*$/); ++ if (prefix === null) { ++ return false; ++ } ++ ++ // Ensure there is no content after the cursor besides possibly the end of the comment ++ const suffix = line.slice(position.character).match(/^\s*\**\/?$/); ++ return suffix !== null; ++ } ++ ++ /** ++ * Try to insert a jsdoc comment, using a template provide by typescript ++ * if possible, otherwise falling back to a default comment format. ++ */ ++ private tryCompleteJsDoc(resource: Uri, position: Position): Thenable { ++ const file = this.client.normalizePath(resource); ++ if (!file) { ++ return Promise.resolve(false); ++ } ++ ++ const editor = window.activeTextEditor; ++ if (!editor || editor.document.uri.fsPath !== resource.fsPath) { ++ return Promise.resolve(false); ++ } ++ ++ return this.prepForDocCompletion(editor, position) ++ .then((start: Position) => { ++ return this.tryInsertJsDocFromTemplate(editor, file, start); ++ }) ++ .then((didInsertFromTemplate: boolean) => { ++ if (didInsertFromTemplate) { ++ return true; ++ } ++ return this.tryInsertDefaultDoc(editor, position); ++ }); ++ } ++ ++ /** ++ * Prepare the area around the position for insertion of the jsdoc. ++ * ++ * Removes any the prefix and suffix of a possible jsdoc ++ */ ++ private prepForDocCompletion(editor: TextEditor, position: Position): Thenable { ++ const line = editor.document.lineAt(position.line).text; ++ const prefix = line.slice(0, position.character).match(/\/\**\s*$/); ++ const suffix = line.slice(position.character).match(/^\s*\**\//); ++ if (!prefix && !suffix) { ++ // Nothing to remove ++ return Promise.resolve(position); ++ } ++ ++ const start = position.translate(0, prefix ? -prefix[0].length : 0); ++ return editor.edit( ++ edits => { ++ edits.delete(new Range(start, position.translate(0, suffix ? suffix[0].length : 0))); ++ }, { ++ undoStopBefore: true, ++ undoStopAfter: false ++ }).then(() => start); ++ } ++ ++ private tryInsertJsDocFromTemplate(editor: TextEditor, file: string, position: Position): Promise { ++ const args: FileLocationRequestArgs = { ++ file: file, ++ line: position.line + 1, ++ offset: position.character + 1 ++ }; ++ return this.client.execute('docCommentTemplate', args) ++ .then((res: DocCommandTemplateResponse) => { ++ if (!res || !res.body) { ++ return false; ++ } ++ const commentText = res.body.newText; ++ return editor.edit( ++ edits => edits.insert(position, commentText), ++ { undoStopBefore: false, undoStopAfter: true }); ++ }, () => false) ++ .then((didInsertComment: boolean) => { ++ if (didInsertComment) { ++ const newCursorPosition = new Position(position.line + 1, editor.document.lineAt(position.line + 1).text.length); ++ editor.selection = new Selection(newCursorPosition, newCursorPosition); ++ } ++ return didInsertComment; ++ }); ++ } ++ ++ /** ++ * Insert the default JSDoc ++ */ ++ private tryInsertDefaultDoc(editor: TextEditor, position: Position): Thenable { ++ const line = editor.document.lineAt(position.line).text; ++ const spaceBefore = line.slice(0, position.character).match(/^\s*$/);",When you use [`SnippetString`](https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.d.ts#L2122) you get indentation for free and you can also define placeholders for params and define the final cursor position.,2017-02-22 15:15:16 +381,"@@ -0,0 +1,2 @@ ++Line 1","Line 1: **Awesome** +",2016-10-23 10:14:11 +382,"@@ -0,0 +1,2 @@ ++Line 1 ++Line 2","Line 2: **Better Even** +",2016-10-23 10:14:31 +576,"@@ -0,0 +1,212 @@ ++/*---------------------------------------------------------------------------------------------",Awesome that we have tests for this!,2016-12-05 14:55:38 +578,"@@ -0,0 +1,212 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import * as assert from 'assert'; ++import { Model as EditorModel } from 'vs/editor/common/model/model'; ++import { IExpression } from 'vs/workbench/parts/debug/common/debug'; ++import { IRange, IModel } from 'vs/editor/common/editorCommon'; ++import { createStringDictionary, IStringDictionary } from 'vs/base/common/collections'; ++import { LineTokens, StandardTokenType } from 'vs/editor/common/core/lineTokens'; ++import * as inlineDecorators from 'vs/workbench/parts/debug/electron-browser/debugInlineDecorators'; ++ ++// Test data ++const testLine = 'function doit(everything, is, awesome, awesome, when, youre, part, of, a, team){}'; ++ ++const testNameValueMap = { ++ everything: '{emmet: true, batman: true, legoUniverse: true}', ++ is: '15', ++ awesome: '""aweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeesome…""', ++ when: 'true', ++ youre: '""Yes I mean you""', ++ part: '""𝄞 ♪ ♫""' ++}; ++ ++suite('Debug - Inline Value Decorators', () => { ++ test('getNameValueMapFromScopeChildren trims long values', () => { ++ const expressions = [ ++ createExpression('hello', 'world'), ++ createExpression('blah', createLongString()) ++ ]; ++ ++ const nameValueMap = inlineDecorators.getNameValueMapFromScopeChildren([expressions]); ++ ++ // Ensure blah is capped and ellipses added ++ assert.deepEqual(nameValueMap, { ++ hello: 'world', ++ blah: '""blah blah blah blah blah blah blah blah blah bla…""' ++ }); ++ }); ++ ++ test('getNameValueMapFromScopeChildren caps scopes to a MAX_NUM_INLINE_VALUES limit', () => { ++ const scopeChildren: IExpression[][] = new Array(5); ++ const expectedNameValueMap: IStringDictionary = createStringDictionary(); ++ ++ // 10 Stack Frames with a 100 scope expressions each ++ // JS Global Scope has 700+ expressions so this is close to a real world scenario ++ for (let i = 0; i < scopeChildren.length; i++) { ++ const expressions = new Array(50); ++ ++ for (let j = 0; j < expressions.length; ++j) { ++ const name = `name${i}.${j}`; ++ const val = `val${i}.${j}`; ++ expressions[j] = createExpression(name, val); ++ ++ if ((i * expressions.length + j) < inlineDecorators.MAX_NUM_INLINE_VALUES) { ++ expectedNameValueMap[name] = val; ++ } ++ } ++ ++ scopeChildren[i] = expressions; ++ } ++ ++ const nameValueMap = inlineDecorators.getNameValueMapFromScopeChildren(scopeChildren); ++ ++ assert.deepEqual(nameValueMap, expectedNameValueMap); ++ }); ++ ++ test('getDecoratorFromNames caps long decorator afterText', () => { ++ const names = Object.keys(testNameValueMap); ++ const lineNumber = 1; ++ const decorator = inlineDecorators.getDecoratorFromNames(lineNumber, names, testNameValueMap, [testLine]); ++ ++ const expectedDecoratorText = ' everything = {emmet: true, batman: true, legoUniverse: true}, is = 15, awesome = ""aweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeesome…"", when = true, youre = ""Yes…'; ++ assert.equal(decorator.renderOptions.dark.after.contentText, decorator.renderOptions.light.after.contentText); ++ assert.equal(decorator.renderOptions.dark.after.contentText, expectedDecoratorText); ++ assert.deepEqual(decorator.range, { ++ startLineNumber: lineNumber, ++ endLineNumber: lineNumber, ++ startColumn: testLine.length, ++ endColumn: testLine.length + 1 ++ }); ++ }); ++ ++ test('getDecorators returns correct decorator afterText', () => { ++ const lineContent = 'console.log(everything, part, part);'; // part shouldn't be duplicated ++ const lineNumber = 1; ++ const wordRangeMap = updateWordRangeMap(createStringDictionary(), lineNumber, lineContent); ++ const decorators = inlineDecorators.getDecorators(testNameValueMap, wordRangeMap, [lineContent]); ++ const expectedDecoratorText = ' everything = {emmet: true, batman: true, legoUniverse: true}, part = ""𝄞 ♪ ♫"" '; ++ assert.equal(decorators[0].renderOptions.dark.after.contentText, expectedDecoratorText); ++ }); ++ ++ test('getEditorWordRangeMap ignores comments and long lines', () => { ++ const expectedWords = 'function, doit, everything, is, awesome, when, youre, part, of, a, team'.split(', '); ++ const editorModel = EditorModel.createFromString(`/** Copyright comment */\n \n${testLine}\n// Test comment\n${createLongString()}\n`); ++ mockEditorModelLineTokens(editorModel); ++ ++ const wordRangeMap = inlineDecorators.getEditorWordRangeMap(editorModel); ++ const words = Object.keys(wordRangeMap); ++ assert.deepEqual(words, expectedWords); ++ }); ++}); ++ ++// Test helpers ++ ++function createExpression(name: string, value: string): IExpression { ++ return { ++ name, ++ value, ++ getId: () => name, ++ hasChildren: false, ++ getChildren: null ++ }; ++} ++ ++function createLongString(): string { ++ let longStr = ''; ++ for (let i = 0; i < 100; ++i) { ++ longStr += 'blah blah blah '; ++ } ++ return `""${longStr}""`; ++} ++ ++// Simple word range creator that maches wordRegex throughout string ++function updateWordRangeMap(wordRangeMap: IStringDictionary, lineNumber: number, lineContent: string): IStringDictionary { ++ const wordRegexp = inlineDecorators.WORD_REGEXP; ++ wordRegexp.lastIndex = 0; // Reset matching ++ ++ while (true) { ++ const wordMatch = wordRegexp.exec(lineContent); ++ if (!wordMatch) { ++ break; ++ } ++ ++ const word = wordMatch[0]; ++ const startOffset = wordMatch.index; ++ const endOffset = startOffset + word.length; ++ ++ const range: IRange = { ++ startColumn: startOffset + 1, ++ endColumn: endOffset + 1, ++ startLineNumber: lineNumber, ++ endLineNumber: lineNumber ++ }; ++ ++ if (!wordRangeMap[word]) { ++ wordRangeMap[word] = []; ++ } ++ ++ wordRangeMap[word].push(range); ++ } ++ ++ return wordRangeMap; ++} ++ ++interface MockToken { ++ tokenType: StandardTokenType; ++ startOffset: number; ++ endOffset: number; ++} ++ ++// Simple tokenizer that separates comments from words ++function mockLineTokens(lineContent: string): LineTokens {","I do not think this method is needed. You could instead reuses model.createFromeString and then on that model get line tokens. +Here's an example [usage](https://github.com/Microsoft/vscode/blob/master/src/vs/editor/test/common/model/textModelWithTokens.test.ts#L283)",2016-12-05 15:08:21 +314,"@@ -0,0 +1,25 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++'use strict'; ++ ++import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; ++import Uri from 'vs/base/common/uri'; ++ ++export const IBackupService = createDecorator('backupService'); ++ ++export interface IBackupService { ++ _serviceBrand: any; ++ ++ getBackupWorkspaces(): string[];","Now I am confused why this guy reaches into the territory of vs/electron-main/backup +",2016-10-13 15:03:02 +48,"@@ -0,0 +1,257 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import {Promise, TPromise} from 'vs/base/common/winjs.base'; ++import {IEventEmitter} from 'vs/base/common/eventEmitter'; ++import {Dimension, Builder, $} from 'vs/base/browser/builder'; ++import {IAction, IActionRunner, Action, ActionRunner} from 'vs/base/common/actions'; ++import {IActionItem, ActionsOrientation} from 'vs/base/browser/ui/actionbar/actionbar'; ++import {WorkbenchComponent} from 'vs/workbench/common/component'; ++import {CompositeEvent} from 'vs/workbench/common/events'; ++import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; ++import {AsyncDescriptor} from 'vs/platform/instantiation/common/descriptors'; ++import {IComposite} from 'vs/workbench/common/composite'; ++import {ISelection, Selection} from 'vs/platform/selection/common/selection'; ++ ++/** ++ * Internal composite events to communicate with composite container. ++ */ ++export const EventType = { ++ INTERNAL_COMPOSITE_TITLE_AREA_UPDATE: 'internalCompositeTitleAreaUpdate' ++}; ++ ++/** ++ * Composites are layed out in the sidebar part of the workbench. Only one composite can be open","@isidorn would rephrase, it is not just sidebar +",2016-01-19 10:43:33 +194,"@@ -0,0 +1,26 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as Types from 'vs/base/common/types'; ++import { AbstractSystemVariables } from 'vs/base/common/parsers'; ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++ ++export class SettingsVariables extends AbstractSystemVariables { ++ private configuration: any; ++ constructor(private configurationService: IConfigurationService) { ++ super(); ++ this.configuration = this.configurationService.getConfiguration(); ++ } ++ ++ protected resolveString(value: string): string { ++ let regexp = /\$\{settings\.(.*?)\}/g;","I would prefer if you just read the configuration every time you need to resolve the string. +Not sure if doing it the current way you can end up with a stale configuration. +",2016-07-06 08:02:09 +195,"@@ -0,0 +1,26 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as Types from 'vs/base/common/types'; ++import { AbstractSystemVariables } from 'vs/base/common/parsers'; ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++ ++export class SettingsVariables extends AbstractSystemVariables { ++ private configuration: any; ++ constructor(private configurationService: IConfigurationService) { ++ super(); ++ this.configuration = this.configurationService.getConfiguration(); ++ } ++ ++ protected resolveString(value: string): string { ++ let regexp = /\$\{settings\.(.*?)\}/g; ++ return value.replace(regexp, (match: string, name: string) => { ++ let config = this.configuration; ++ let newValue = new Function('_', 'try {return _.' + name + ';} catch (ex) { return """";}')(config); ++ return Types.isString(newValue) ? newValue : '';","We try to avoid using the 'new Function' pattern, is it possible to re-write this using a lambda function - it would read much nicer? +",2016-07-06 08:03:47 +946,"@@ -0,0 +1,280 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++import * as vscode from 'vscode'; ++import * as interfaces from './interfaces'; ++import ContentProvider from './contentProvider'; ++import * as path from 'path'; ++import { loadMessageBundle } from 'vscode-nls'; ++const localize = loadMessageBundle(); ++ ++const messages = { ++ cursorNotInConflict: 'Editor cursor is not within a merge conflict', ++ cursorOnSplitterRange: 'Editor cursor is within the merge conflict splitter, please move it to either the ""current"" or ""incoming"" block', ++ noConflicts: 'No merge conflicts found in this file', ++ noOtherConflictsInThisFile: 'No other merge conflicts within this file' ++}; ++ ++interface IDocumentMergeConflictNavigationResults { ++ canNavigate: boolean; ++ conflict?: interfaces.IDocumentMergeConflict; ++} ++ ++enum NavigationDirection { ++ Forwards, ++ Backwards ++} ++ ++export default class CommandHandler implements vscode.Disposable { ++ ++ private disposables: vscode.Disposable[] = []; ++ ++ constructor(private context: vscode.ExtensionContext, private tracker: interfaces.IDocumentMergeConflictTracker) { ++ } ++ ++ begin() { ++ this.disposables.push( ++ vscode.commands.registerTextEditorCommand('merge-conflict.accept.current', this.acceptCurrent, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.accept.incoming', this.acceptIncoming, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.accept.selection', this.acceptSelection, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.accept.both', this.acceptBoth, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.accept.all-current', this.acceptAllCurrent, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.accept.all-incoming', this.acceptAllIncoming, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.accept.all-both', this.acceptAllBoth, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.next', this.navigateNext, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.previous', this.navigatePrevious, this), ++ vscode.commands.registerTextEditorCommand('merge-conflict.compare', this.compare, this) ++ ); ++ } ++ ++ acceptCurrent(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args): Promise { ++ return this.accept(interfaces.CommitType.Current, editor, ...args); ++ } ++ ++ acceptIncoming(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args): Promise { ++ return this.accept(interfaces.CommitType.Incoming, editor, ...args); ++ } ++ ++ acceptBoth(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args): Promise { ++ return this.accept(interfaces.CommitType.Both, editor, ...args); ++ } ++ ++ acceptAllCurrent(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args): Promise { ++ return this.acceptAll(interfaces.CommitType.Current, editor); ++ } ++ ++ acceptAllIncoming(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args): Promise { ++ return this.acceptAll(interfaces.CommitType.Incoming, editor); ++ } ++ ++ acceptAllBoth(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args): Promise { ++ return this.acceptAll(interfaces.CommitType.Both, editor); ++ } ++ ++ async compare(editor: vscode.TextEditor, edit: vscode.TextEditorEdit, conflict: interfaces.IDocumentMergeConflict | null, ...args) { ++ const fileName = path.basename(editor.document.uri.fsPath); ++ ++ // No conflict, command executed from command palette ++ if (!conflict) { ++ conflict = await this.findConflictContainingSelection(editor); ++ ++ // Still failed to find conflict, warn the user and exit ++ if (!conflict) { ++ vscode.window.showWarningMessage(localize('cursorNotInConflict', messages.cursorNotInConflict)); ++ return; ++ } ++ } ++ ++ let range = conflict.current.content; ++ const leftUri = editor.document.uri.with({ ++ scheme: ContentProvider.scheme, ++ query: JSON.stringify(range) ++ }); ++ ++ const leftTitle = `Current changes`; // (Ln ${range.start.line}${!range.isSingleLine ? `-${range.end.line}` : ''})`; ++ ++ range = conflict.incoming.content; ++ const rightUri = leftUri.with({ query: JSON.stringify(range) }); ++ ++ const rightTitle = `Incoming changes`; // (Ln${range.start.line}${!range.isSingleLine ? `-${range.end.line}` : ''})`; ++ ++ const title = `${fileName}: ${leftTitle} \u2194 ${rightTitle}`;",Maybe inline the two titles and use a placeholder `{0}` to localize like: https://github.com/Microsoft/vscode/blame/master/extensions/git/src/commands.ts#L754,2017-05-23 18:16:30 +207,"@@ -0,0 +1,29 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++'use strict'; ++ ++import * as Types from 'vs/base/common/types'; ++import { SystemVariables } from './systemVariables'; ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; ++import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; ++import URI from 'vs/base/common/uri'; ++ ++export class ConfigVariables extends SystemVariables { ++ constructor(private configurationService: IConfigurationService, editorService: IWorkbenchEditorService, contextService: IWorkspaceContextService, workspaceRoot: URI = null, envVariables: { [key: string]: string } = process.env) { ++ super(editorService, contextService, workspaceRoot, envVariables); ++ } ++ ++ protected resolveString(value: string): string { ++ value = super.resolveString(value); ++","The regexp should have 'config' not 'settings' to allign with other places where we have replacments. +",2016-07-08 13:56:00 +18,"@@ -0,0 +1,295 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++","Is this actually our copyright and was this copied from some public source? +",2015-11-27 08:45:20 +19,"@@ -0,0 +1,295 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++export class HTMLTagSpecification { ++ constructor(public label: string, public attributes: string[] = []) {} ++} ++ ++// HTML tag information sourced from http://www.w3.org/TR/2015/WD-html51-20151008/ ++export const HTML_TAGS : { [tag:string]: HTMLTagSpecification } = {","@Tyriar I meat this. @chrisdias will know how to attribute properly... +",2015-11-27 11:59:40 +187,"@@ -0,0 +1,30 @@ ++## Using Markdown-it Plugins ++ ++To use a `markdown-it` plugin, goto the directory containing the `markdown-it` extension. This will ++be found in the `extensions` folder in your vscode installation. Install the `markdown-it` plugin ++as a node module. For example, to install the `KaTeX` markdown-it extension you would simply type: ++ ++``` sh ++npm install markdown-it-katex ++``` ++ ++Next, add the plugin into your [settings configuration](https://code.visualstudio.com/docs/customization/userandworkspace) ++under the `""markdown.plugs""` namespace. This setting should contain a list for each `markdown-it` extension you wish ++to install. The list should contain an object describing the name of the module, a list of styles that your extentsion ++may require, and options that you wish to pass to your extension. For example, while installing the `markdown-it-katex` ++extension we would include this in your settings configuration: ++ ++``` json ++ ""markdown.plugins"": [ ++ { ++ ""name"": ""markdown-it-katex"", ++ ""styles"": [","Just curious, is it necessary to have separate styling for plugins? +",2016-06-20 09:59:36 +619,"@@ -0,0 +1,30 @@ ++ ++ ++ @@NAME@@.desktop ++ CC-BY-SA-3.0",Let's leave this as MIT for now as I don't think we use a special license for metadata.,2016-12-16 18:57:04 +618,"@@ -0,0 +1,30 @@ ++ ++ ++ @@NAME@@.desktop ++ CC-BY-SA-3.0 ++ MIT",This can be sourced from `product.licenseName` now.,2016-12-16 18:56:21 +802,"@@ -0,0 +1,32 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ","@mjbvz is there a specific need to introduce preload.js here? I would rather want to keep this JS close to the file because it is about updating the background color. Slower loading can result in ugly flicker otherwise. + +Is it because of the `unsafe-inline` CSP?",2017-06-14 05:44:41 +284,"@@ -3,6 +3,7 @@ npm-debug.log + Thumbs.db + node_modules/ + .build/ ++.vscode/.browse.VC* ","Please remove this one, you can use `.git/info/exclude` for it +",2016-09-21 06:17:16 +990,"@@ -3,9 +3,6 @@ + ""version"": ""0.1.0"", + ""publisher"": ""vscode"", + ""engines"": { ""vscode"": ""*"" }, +- ""scripts"": {",Please keep the script and point it to the repo that has the improved grammar.,2017-06-19 13:55:51 +456,"@@ -30,11 +30,12 @@ import { IResourceInput, IEditorInput } from 'vs/platform/editor/common/editor'; + import { IModeService } from 'vs/editor/common/services/modeService'; + import { getIconClasses } from 'vs/workbench/browser/labels'; + import { IModelService } from 'vs/editor/common/services/modelService'; +-import { EditorInput, getUntitledOrFileResource, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; ++// import { EditorInput, getUntitledOrFileResource, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor';","@wprater why commented out? +",2016-11-05 07:39:37 +200,"@@ -30,6 +30,7 @@ export class TerminalPanel extends Panel { + private actions: IAction[]; + private parentDomElement: HTMLElement; + private terminalContainer: HTMLElement; ++ private currentThemeId: string;","Make this `currentBaseThemeId` +",2016-07-06 22:59:29 +292,"@@ -30,6 +30,7 @@ namespace schema { + case 'editor/title': return MenuId.EditorTitle; + case 'editor/context': return MenuId.EditorContext; + case 'explorer/context': return MenuId.ExplorerContext; ++ case 'editor/tab': return MenuId.EditorTab;","maybe better editor/tab/context or editor/context/tab? +",2016-10-04 10:49:29 +103,"@@ -300,6 +303,25 @@ export class WorkingFilesModel implements IWorkingFilesModel { + return null; + } + ++ public restoreRecentlyRemovedEntry(): WorkingFileEntry {","I think I would change the data structure of recently closed entries so that it alway is an array (of up to N entries) so that you can perform the reopening multiple times as needed. + +You have to be aware of the fact that you can have untitled files in the list, I suggest to ignore any entry in the working files list of closed entries that is not file thereby. + +Another interesting aspect is that we remove a working file automatically if a file gets deleted. So a remove of an entry might not necessarily be via user interaction. This might change in the future though, because it also has its own set of issues. But it would be weird to reopen a deleted file. +",2016-04-09 14:44:12 +12,"@@ -3012,6 +3012,11 @@ declare namespace vscode { + export const onDidChangeTextDocument: Event; + + /** ++ * An event that is emitted when a [text document](#TextDocument) is saving to disk (save may fail). ++ */ ++ export const onSavingTextDocument: Event;","wrong name. must be `onWillSaveTextDocument` +",2015-11-24 09:10:38 +305,"@@ -306,7 +305,12 @@ function setupIPC(accessor: ServicesAccessor): TPromise { + promise = service.getMainProcessId() + .then(processId => { + logService.log('Sending some foreground love to the running instance:', processId); +- allowSetForegroundWindow(processId); ++ try { ++ const { allowSetForegroundWindow } = require.__$__nodeRequire('windows-foreground-love');","@the-ress this is rather ugly, can we do what windows-mutex does? This native module is also only build for Windows and it still has a nice import 👍 +",2016-10-05 17:36:06 +870,"@@ -308,4 +542,556 @@ export function processNlsFiles(opts:{fileHeader:string;}): ThroughStream { + } + this.emit('data', file); + }); ++} ++ ++export function prepareXlfFiles(projectName?: string, extensionName?: string): ThroughStream { ++ return through( ++ function (file: File) { ++ if (!file.isBuffer()) { ++ log('Error', `Failed to read component file: ${file.relative}`); ++ } ++ ++ const extension = path.extname(file.path); ++ if (extension === '.json') { ++ const json = JSON.parse((file.contents).toString('utf8')); ++ ++ if (BundledFormat.is(json)) { ++ importBundleJson(file, json, this); ++ } else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) { ++ importModuleOrPackageJson(file, json, projectName, this, extensionName); ++ } else { ++ log('Error', 'JSON format cannot be deduced.'); ++ } ++ } else if (extension === '.isl') { ++ importIsl(file, this); ++ } ++ } ++ ); ++} ++ ++export function getResource(sourceFile: string): Resource { ++ const editorProject: string = 'vscode-editor', ++ workbenchProject: string = 'vscode-workbench'; ++ let resource: string; ++ ++ if (sourceFile.startsWith('vs/platform')) { ++ return { name: 'vs/platform', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/editor/contrib')) { ++ return { name: 'vs/editor/contrib', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/editor')) { ++ return { name: 'vs/editor', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/base')) { ++ return { name: 'vs/base', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/code')) { ++ return { name: 'vs/code', project: workbenchProject }; ++ } else if (sourceFile.startsWith('vs/workbench/parts')) { ++ resource = sourceFile.split('/', 4).join('/'); ++ return { name: resource, project: workbenchProject }; ++ } else if (sourceFile.startsWith('vs/workbench/services')) { ++ resource = sourceFile.split('/', 4).join('/'); ++ return { name: resource, project: workbenchProject }; ++ } else if (sourceFile.startsWith('vs/workbench')) { ++ return { name: 'vs/workbench', project: workbenchProject }; ++ } ++ ++ throw new Error (`Could not identify the XLF bundle for ${sourceFile}`); ++} ++ ++ ++function importBundleJson(file: File, json: BundledFormat, stream: ThroughStream): void { ++ let bundleXlfs: Map = Object.create(null); ++ ++ for (let source in json.keys) { ++ const projectResource = getResource(source); ++ const resource = projectResource.name; ++ const project = projectResource.project; ++ ++ const keys = json.keys[source]; ++ const messages = json.messages[source]; ++ if (keys.length !== messages.length) { ++ log('Error:', `There is a mismatch between keys and messages in ${file.relative}`); ++ } ++ ++ let xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project); ++ xlf.addFile('src/' + source, keys, messages); ++ } ++ ++ for (let resource in bundleXlfs) { ++ const newFilePath = `${bundleXlfs[resource].project}/${resource.replace(/\//g, '_')}.xlf`; ++ const xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8')}); ++ stream.emit('data', xlfFile); ++ } ++} ++ ++// Keeps existing XLF instances and a state of how many files were already processed for faster file emission ++var extensions: Map<{ xlf: XLF, processed: number }> = Object.create(null); ++function importModuleOrPackageJson(file: File, json: ModuleJsonFormat | PackageJsonFormat, projectName: string, stream: ThroughStream, extensionName?: string): void { ++ if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) { ++ log('Error:', `There is a mismatch between keys and messages in ${file.relative}`); ++ } ++ ++ // Prepare the source path for attribute in XLF & extract messages from JSON ++ const formattedSourcePath = file.relative.replace(/\\/g, '/'); ++ const messages = Object.keys(json).map((key) => json[key].toString()); ++ ++ // Stores the amount of localization files to be transformed to XLF before the emission ++ let localizationFilesCount, ++ originalFilePath; ++ // If preparing XLF for external extension, then use different glob pattern and source path ++ if (extensionName) { ++ localizationFilesCount = glob.sync('**/*.nls.json').length; ++ originalFilePath = `${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`; ++ } else { ++ // Used for vscode/extensions folder ++ extensionName = formattedSourcePath.split('/')[0]; ++ localizationFilesCount = glob.sync(`./extensions/${extensionName}/**/*.nls.json`).length; ++ originalFilePath = `extensions/${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`; ++ } ++ ++ let extension = extensions[extensionName] ? ++ extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 }; ++ ++ if (ModuleJsonFormat.is(json)) { ++ extension.xlf.addFile(originalFilePath, json['keys'], json['messages']); ++ } else { ++ extension.xlf.addFile(originalFilePath, Object.keys(json), messages); ++ } ++ ++ // Check if XLF is populated with file nodes to emit it ++ if (++extensions[extensionName].processed === localizationFilesCount) { ++ const newFilePath = path.join(projectName, extensionName + '.xlf'); ++ const xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8')}); ++ stream.emit('data', xlfFile); ++ } ++} ++ ++var islXlf: XLF, ++ islProcessed: number = 0; ++ ++function importIsl(file: File, stream: ThroughStream) { ++ const islFiles = ['Default.isl', 'messages.en.isl']; ++ const projectName = 'vscode-workbench'; ++ ++ let xlf = islXlf ? islXlf : islXlf = new XLF(projectName), ++ keys: string[] = [], ++ messages: string[] = []; ++ ++ let model = new TextModel(file.contents.toString()); ++ let inMessageSection = false; ++ model.lines.forEach(line => { ++ if (line.length === 0) { ++ return; ++ } ++ let firstChar = line.charAt(0); ++ switch (firstChar) { ++ case ';': ++ // Comment line; ++ return; ++ case '[': ++ inMessageSection = '[Messages]' === line || '[CustomMessages]' === line; ++ return; ++ } ++ if (!inMessageSection) { ++ return; ++ } ++ let sections: string[] = line.split('='); ++ if (sections.length !== 2) { ++ log('Error:', `Badly formatted message found: ${line}`); ++ } else { ++ let key = sections[0]; ++ let value = sections[1]; ++ if (key.length > 0 && value.length > 0) { ++ keys.push(key); ++ messages.push(value); ++ } ++ } ++ }); ++ ++ const originalPath = file.path.substring(file.cwd.length+1, file.path.split('.')[0].length).replace(/\\/g, '/'); ++ xlf.addFile(originalPath, keys, messages); ++ ++ // Emit only upon all ISL files combined into single XLF instance ++ if (++islProcessed === islFiles.length) { ++ const newFilePath = path.join(projectName, 'setup.xlf'); ++ const xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8')}); ++ stream.emit('data', xlfFile); ++ } ++} ++ ++export function pushXlfFiles(apiHostname: string, username: string, password: string): ThroughStream { ++ let tryGetPromises = []; ++ let updateCreatePromises = []; ++ ++ return through(function(file: File) { ++ const project = path.dirname(file.relative); ++ const fileName = path.basename(file.path); ++ const slug = fileName.substr(0, fileName.length - '.xlf'.length); ++ const credentials = `${username}:${password}`; ++ ++ // Check if resource already exists, if not, then create it. ++ let promise = tryGetResource(project, slug, apiHostname, credentials); ++ tryGetPromises.push(promise); ++ promise.then(exists => { ++ if (exists) { ++ promise = updateResource(project, slug, file, apiHostname, credentials); ++ } else { ++ promise = createResource(project, slug, file, apiHostname, credentials); ++ } ++ updateCreatePromises.push(promise); ++ }).catch((reason) => {",I am not a gulp expert either but I think this simply logs something to the console but the gulp stream says in tact and the build will look like it passed. We have to ensure that in the cause of exceptions talking to Transifex this can be observed as a failing build from the outside.,2017-04-04 13:06:52 +871,"@@ -308,4 +542,556 @@ export function processNlsFiles(opts:{fileHeader:string;}): ThroughStream { + } + this.emit('data', file); + }); ++} ++ ++export function prepareXlfFiles(projectName?: string, extensionName?: string): ThroughStream { ++ return through( ++ function (file: File) { ++ if (!file.isBuffer()) { ++ log('Error', `Failed to read component file: ${file.relative}`); ++ } ++ ++ const extension = path.extname(file.path); ++ if (extension === '.json') { ++ const json = JSON.parse((file.contents).toString('utf8')); ++ ++ if (BundledFormat.is(json)) { ++ importBundleJson(file, json, this); ++ } else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) { ++ importModuleOrPackageJson(file, json, projectName, this, extensionName); ++ } else { ++ log('Error', 'JSON format cannot be deduced.'); ++ } ++ } else if (extension === '.isl') { ++ importIsl(file, this); ++ } ++ } ++ ); ++} ++ ++export function getResource(sourceFile: string): Resource { ++ const editorProject: string = 'vscode-editor', ++ workbenchProject: string = 'vscode-workbench'; ++ let resource: string; ++ ++ if (sourceFile.startsWith('vs/platform')) { ++ return { name: 'vs/platform', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/editor/contrib')) { ++ return { name: 'vs/editor/contrib', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/editor')) { ++ return { name: 'vs/editor', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/base')) { ++ return { name: 'vs/base', project: editorProject }; ++ } else if (sourceFile.startsWith('vs/code')) { ++ return { name: 'vs/code', project: workbenchProject }; ++ } else if (sourceFile.startsWith('vs/workbench/parts')) { ++ resource = sourceFile.split('/', 4).join('/'); ++ return { name: resource, project: workbenchProject }; ++ } else if (sourceFile.startsWith('vs/workbench/services')) { ++ resource = sourceFile.split('/', 4).join('/'); ++ return { name: resource, project: workbenchProject }; ++ } else if (sourceFile.startsWith('vs/workbench')) { ++ return { name: 'vs/workbench', project: workbenchProject }; ++ } ++ ++ throw new Error (`Could not identify the XLF bundle for ${sourceFile}`); ++} ++ ++ ++function importBundleJson(file: File, json: BundledFormat, stream: ThroughStream): void { ++ let bundleXlfs: Map = Object.create(null); ++ ++ for (let source in json.keys) { ++ const projectResource = getResource(source); ++ const resource = projectResource.name; ++ const project = projectResource.project; ++ ++ const keys = json.keys[source]; ++ const messages = json.messages[source]; ++ if (keys.length !== messages.length) { ++ log('Error:', `There is a mismatch between keys and messages in ${file.relative}`); ++ } ++ ++ let xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project); ++ xlf.addFile('src/' + source, keys, messages); ++ } ++ ++ for (let resource in bundleXlfs) { ++ const newFilePath = `${bundleXlfs[resource].project}/${resource.replace(/\//g, '_')}.xlf`; ++ const xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8')}); ++ stream.emit('data', xlfFile); ++ } ++} ++ ++// Keeps existing XLF instances and a state of how many files were already processed for faster file emission ++var extensions: Map<{ xlf: XLF, processed: number }> = Object.create(null); ++function importModuleOrPackageJson(file: File, json: ModuleJsonFormat | PackageJsonFormat, projectName: string, stream: ThroughStream, extensionName?: string): void { ++ if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) { ++ log('Error:', `There is a mismatch between keys and messages in ${file.relative}`); ++ } ++ ++ // Prepare the source path for attribute in XLF & extract messages from JSON ++ const formattedSourcePath = file.relative.replace(/\\/g, '/'); ++ const messages = Object.keys(json).map((key) => json[key].toString()); ++ ++ // Stores the amount of localization files to be transformed to XLF before the emission ++ let localizationFilesCount, ++ originalFilePath; ++ // If preparing XLF for external extension, then use different glob pattern and source path ++ if (extensionName) { ++ localizationFilesCount = glob.sync('**/*.nls.json').length; ++ originalFilePath = `${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`; ++ } else { ++ // Used for vscode/extensions folder ++ extensionName = formattedSourcePath.split('/')[0]; ++ localizationFilesCount = glob.sync(`./extensions/${extensionName}/**/*.nls.json`).length; ++ originalFilePath = `extensions/${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`; ++ } ++ ++ let extension = extensions[extensionName] ? ++ extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 }; ++ ++ if (ModuleJsonFormat.is(json)) { ++ extension.xlf.addFile(originalFilePath, json['keys'], json['messages']); ++ } else { ++ extension.xlf.addFile(originalFilePath, Object.keys(json), messages); ++ } ++ ++ // Check if XLF is populated with file nodes to emit it ++ if (++extensions[extensionName].processed === localizationFilesCount) { ++ const newFilePath = path.join(projectName, extensionName + '.xlf'); ++ const xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8')}); ++ stream.emit('data', xlfFile); ++ } ++} ++ ++var islXlf: XLF, ++ islProcessed: number = 0; ++ ++function importIsl(file: File, stream: ThroughStream) { ++ const islFiles = ['Default.isl', 'messages.en.isl']; ++ const projectName = 'vscode-workbench'; ++ ++ let xlf = islXlf ? islXlf : islXlf = new XLF(projectName), ++ keys: string[] = [], ++ messages: string[] = []; ++ ++ let model = new TextModel(file.contents.toString()); ++ let inMessageSection = false; ++ model.lines.forEach(line => { ++ if (line.length === 0) { ++ return; ++ } ++ let firstChar = line.charAt(0); ++ switch (firstChar) { ++ case ';': ++ // Comment line; ++ return; ++ case '[': ++ inMessageSection = '[Messages]' === line || '[CustomMessages]' === line; ++ return; ++ } ++ if (!inMessageSection) { ++ return; ++ } ++ let sections: string[] = line.split('='); ++ if (sections.length !== 2) { ++ log('Error:', `Badly formatted message found: ${line}`); ++ } else { ++ let key = sections[0]; ++ let value = sections[1]; ++ if (key.length > 0 && value.length > 0) { ++ keys.push(key); ++ messages.push(value); ++ } ++ } ++ }); ++ ++ const originalPath = file.path.substring(file.cwd.length+1, file.path.split('.')[0].length).replace(/\\/g, '/'); ++ xlf.addFile(originalPath, keys, messages); ++ ++ // Emit only upon all ISL files combined into single XLF instance ++ if (++islProcessed === islFiles.length) { ++ const newFilePath = path.join(projectName, 'setup.xlf'); ++ const xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8')}); ++ stream.emit('data', xlfFile); ++ } ++} ++ ++export function pushXlfFiles(apiHostname: string, username: string, password: string): ThroughStream { ++ let tryGetPromises = []; ++ let updateCreatePromises = []; ++ ++ return through(function(file: File) { ++ const project = path.dirname(file.relative); ++ const fileName = path.basename(file.path); ++ const slug = fileName.substr(0, fileName.length - '.xlf'.length); ++ const credentials = `${username}:${password}`; ++ ++ // Check if resource already exists, if not, then create it. ++ let promise = tryGetResource(project, slug, apiHostname, credentials); ++ tryGetPromises.push(promise); ++ promise.then(exists => { ++ if (exists) { ++ promise = updateResource(project, slug, file, apiHostname, credentials); ++ } else { ++ promise = createResource(project, slug, file, apiHostname, credentials); ++ } ++ updateCreatePromises.push(promise); ++ }).catch((reason) => { ++ log('Error:', reason); ++ }); ++ ++ }, function() { ++ // End the pipe only after all the communication with Transifex API happened ++ Promise.all(tryGetPromises).then(() => { ++ Promise.all(updateCreatePromises).then(() => { ++ this.emit('end'); ++ }).catch((reason) => log('Error:', reason)); ++ }).catch((reason) => log('Error:', reason)); ++ }); ++} ++ ++function tryGetResource(project: string, slug: string, apiHostname: string, credentials: string): Promise { ++ return new Promise((resolve, reject) => { ++ const options = { ++ hostname: apiHostname, ++ path: `/api/2/project/${project}/resource/${slug}/?details`, ++ auth: credentials, ++ method: 'GET' ++ }; ++ ++ const request = http.request(options, (response) => { ++ if (response.statusCode === 404) { ++ resolve(false); ++ } else if (response.statusCode === 200) { ++ resolve(true); ++ } else { ++ reject(`Failed to query resource ${project}/${slug}. Response: ${response.statusCode} ${response.statusMessage}`); ++ } ++ }).on('error', (err) => { ++ reject(`Failed to get ${project}/${slug} on Transifex: ${err}`); ++ }); ++ ++ request.end(); ++ }); ++} ++ ++function createResource(project: string, slug: string, xlfFile: File, apiHostname: string, credentials: any): Promise { ++ return new Promise((resolve, reject) => { ++ const data = JSON.stringify({ ++ 'content': xlfFile.contents.toString(), ++ 'name': slug, ++ 'slug': slug, ++ 'i18n_type': 'XLIFF' ++ }); ++ const options = { ++ hostname: apiHostname, ++ path: `/api/2/project/${project}/resources`, ++ headers: { ++ 'Content-Type': 'application/json', ++ 'Content-Length': Buffer.byteLength(data) ++ }, ++ auth: credentials, ++ method: 'POST' ++ }; ++ ++ let request = http.request(options, (res) => { ++ if (res.statusCode === 201) { ++ log(`Resource ${project}/${slug} successfully created on Transifex.`); ++ } else { ++ reject(`Something went wrong in the request creating ${slug} in ${project}. ${res.statusCode}`); ++ } ++ }).on('error', (err) => { ++ reject(`Failed to create ${project}/${slug} on Transifex: ${err}`); ++ }); ++ ++ request.write(data); ++ request.end(); ++ }); ++} ++ ++/** ++ * The following link provides information about how Transifex handles updates of a resource file: ++ * https://dev.befoolish.co/tx-docs/public/projects/updating-content#what-happens-when-you-update-files ++ */ ++function updateResource(project: string, slug: string, xlfFile: File, apiHostname: string, credentials: string) : Promise { ++ return new Promise((resolve, reject) => { ++ const data = JSON.stringify({ content: xlfFile.contents.toString() }); ++ const options = { ++ hostname: apiHostname, ++ path: `/api/2/project/${project}/resource/${slug}/content`, ++ headers: { ++ 'Content-Type': 'application/json', ++ 'Content-Length': Buffer.byteLength(data) ++ }, ++ auth: credentials, ++ method: 'PUT' ++ }; ++ ++ let request = http.request(options, (res) => { ++ if (res.statusCode === 200) { ++ res.setEncoding('utf8'); ++ ++ let responseBuffer: string = ''; ++ res.on('data', function (chunk) { ++ responseBuffer += chunk; ++ }); ++ res.on('end', () => { ++ const response = JSON.parse(responseBuffer); ++ log(`Resource ${project}/${slug} successfully updated on Transifex. Strings added: ${response.strings_added}, updated: ${response.strings_added}, deleted: ${response.strings_added}`); ++ resolve(); ++ }); ++ } else { ++ reject(`Something went wrong in the request updating ${slug} in ${project}. ${res.statusCode}`); ++ } ++ }).on('error', (err) => { ++ reject(`Failed to update ${project}/${slug} on Transifex: ${err}`); ++ }); ++ ++ request.write(data); ++ request.end(); ++ }); ++} ++ ++function getMetadataResources(pathToMetadata: string) : Resource[] { ++ const metadata = fs.readFileSync(pathToMetadata).toString('utf8'); ++ const json = JSON.parse(metadata); ++ let slugs = []; ++ ++ for (let source in json['keys']) { ++ let projectResource = getResource(source); ++ if (!slugs.find(slug => slug.name === projectResource.name && slug.project === projectResource.project)) { ++ slugs.push(projectResource); ++ } ++ } ++ ++ return slugs; ++} ++ ++function obtainProjectResources(projectName: string): Resource[] { ++ let resources: Resource[]; ++ ++ if (projectName === 'vscode-editor-workbench') { ++ resources = getMetadataResources('./out-vscode/nls.metadata.json'); ++ resources.push({ name: 'setup', project: 'vscode-workbench' }); ++ } else if (projectName === 'vscode-extensions') { ++ let extensionsToLocalize: string[] = glob.sync('./extensions/**/*.nls.json').map(extension => extension.split('/')[2]); ++ let resourcesToPull: string[] = []; ++ resources = []; ++ ++ extensionsToLocalize.forEach(extension => { ++ if (resourcesToPull.indexOf(extension) === -1) { // remove duplicate elements returned by glob ++ resourcesToPull.push(extension); ++ resources.push({ name: extension, project: projectName }); ++ } ++ }); ++ } ++ ++ return resources; ++} ++ ++export function pullXlfFiles(projectName: string, apiHostname: string, username: string, password: string, resources?: Resource[]): NodeJS.ReadableStream { ++ if (!resources) { ++ resources = obtainProjectResources(projectName); ++ } ++ if (!resources) { ++ throw new Error('Transifex projects and resources must be defined to be able to pull translations from Transifex.'); ++ } ++ ++ const credentials = `${username}:${password}`; ++ let expectedTranslationsCount = vscodeLanguages.length * resources.length; ++ let translationsRetrieved = 0, called = false; ++ ++ return readable(function(count, callback) { ++ // Mark end of stream when all resources were retrieved ++ if (translationsRetrieved === expectedTranslationsCount) { ++ return this.emit('end'); ++ } ++ ++ if (!called) { ++ called = true; ++ const stream = this; ++ ++ vscodeLanguages.map(function(language) { ++ resources.map(function (resource) { ++ const slug = resource.name.replace(/\//g, '_'); ++ const project = resource.project; ++ const iso639 = iso639_3_to_2[language]; ++ const options = { ++ hostname: apiHostname, ++ path: `/api/2/project/${project}/resource/${slug}/translation/${iso639}?file&mode=onlyreviewed`, ++ auth: credentials, ++ method: 'GET' ++ }; ++ ++ let request = http.request(options, (res) => { ++ let xlfBuffer: string = ''; ++ res.on('data', (data) => xlfBuffer += data); ++ res.on('end', () => { ++ if (res.statusCode === 200) { ++ stream.emit('data', new File({ contents: new Buffer(xlfBuffer) })); ++ } else { ++ log('Error:', `${slug} in ${project} returned no data. Response code: ${res.statusCode}.`); ++ } ++ translationsRetrieved++; ++ }); ++ }).on('error', (err) => { ++ log('Error:', `Failed to query resource ${slug} with the following error: ${err}`); ++ }); ++ request.end(); ++ }); ++ }); ++ } ++ ++ callback(); ++ }); ++} ++ ++export function prepareJsonFiles(): ThroughStream { ++ return through(function(xlf: File) { ++ let stream = this; ++ ++ XLF.parse(xlf.contents.toString()).then( ++ function(resolvedFiles) { ++ resolvedFiles.forEach(file => { ++ let messages = file.messages, translatedFile; ++ ++ // ISL file path always starts with 'build/' ++ if (file.originalFilePath.startsWith('build/')) { ++ const defaultLanguages = { 'zh-cn': true, 'zh-tw': true, 'ko': true }; ++ if (path.basename(file.originalFilePath) === 'Default' && !defaultLanguages[file.language]) { ++ return; ++ } ++ ++ translatedFile = createIslFile('..', file.originalFilePath, messages, iso639_2_to_3[file.language]); ++ } else { ++ translatedFile = createI18nFile(iso639_2_to_3[file.language], file.originalFilePath, messages); ++ } ++ ++ stream.emit('data', translatedFile); ++ }); ++ }, ++ function(rejectReason) { ++ log('Error:', rejectReason); ++ } ++ ); ++ }); ++} ++ ++export function createI18nFile(base: string, originalFilePath: string, messages: Map): File { ++ let content = [ ++ '/*---------------------------------------------------------------------------------------------', ++ ' * Copyright (c) Microsoft Corporation. All rights reserved.', ++ ' * Licensed under the MIT License. See License.txt in the project root for license information.', ++ ' *--------------------------------------------------------------------------------------------*/', ++ '// Do not edit this file. It is machine generated.' ++ ].join('\n') + '\n' + JSON.stringify(messages, null, '\t').replace(/\r\n/g, '\n'); ++ ++ return new File({ ++ path: path.join(base, originalFilePath + '.i18n.json'), ++ contents: new Buffer(content, 'utf8') ++ }); ++} ++ ++ ++const languageNames: Map = { ++ 'chs': 'Simplified Chinese', ++ 'cht': 'Traditional Chinese', ++ 'kor': 'Korean' ++}; ++ ++const languageIds: Map = { ++ 'chs': '$0804', ++ 'cht': '$0404', ++ 'kor': '$0412' ++}; ++ ++const encodings: Map = { ++ 'chs': 'CP936', ++ 'cht': 'CP950', ++ 'jpn': 'CP932', ++ 'kor': 'CP949', ++ 'deu': 'CP1252', ++ 'fra': 'CP1252', ++ 'esn': 'CP1252', ++ 'rus': 'CP1251', ++ 'ita': 'CP1252' ++}; ++ ++export function createIslFile(base: string, originalFilePath: string, messages: Map, language: string): File {",Did you consider that for the ISL we only need to push ch* and kor. For all other languages we have translations. Or is this not possible since languages are defined by a Transifex project. If so we might want to consider not pushing the Default.isl to Transifex,2017-04-04 13:10:34 +221,"@@ -308,7 +340,12 @@ export class OpenAnythingHandler extends QuickOpenHandler { + entry.setHighlights(labelHighlights, descriptionHighlights); + }); + +- return viewResults; ++ return {","Can we make this nicer? E.g. an interface which has one entry for results and another for all performance/telemetry relevant data? Maybe just a Tupel<2>? +",2016-07-14 17:36:35 +477,"@@ -31,26 +33,37 @@ export class UntitledEditorModel extends StringEditorModel implements IEncodingS + + private hasAssociatedFilePath: boolean; + ++ private backupPromises: TPromise[];","@Tyriar this is not being used? and related code around canceling it? +",2016-11-09 07:46:47 +476,"@@ -31,26 +33,37 @@ export class UntitledEditorModel extends StringEditorModel implements IEncodingS + + private hasAssociatedFilePath: boolean; + ++ private backupPromises: TPromise[]; ++ + constructor( + value: string, + modeId: string, + resource: URI, + hasAssociatedFilePath: boolean, + @IModeService modeService: IModeService, + @IModelService modelService: IModelService, +- @IConfigurationService private configurationService: IConfigurationService ++ @IFileService private fileService: IFileService,","@Tyriar unused `fileService` and `backupFileService` +",2016-11-09 07:46:05 +899,"@@ -31,7 +31,8 @@ class ExpandAbbreviationAction extends BasicEmmetEditorAction { + EditorContextKeys.hasOnlyEmptySelection, + EditorContextKeys.hasSingleSelection, + EditorContextKeys.tabDoesNotMoveFocus, +- ContextKeyExpr.has('config.emmet.triggerExpansionOnTab') ++ ContextKeyExpr.has('config.emmet.triggerExpansionOnTab'), ++ ContextKeyExpr.not('config.emmet.autocomplete')",Shouldn't we have a schema definition for this? Like for other values: https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/parts/emmet/node/emmet.contribution.ts#L38,2017-04-25 07:18:32 +975,"@@ -310,6 +310,10 @@ export class ViewletActionItem extends ActivityActionItem { + public render(container: HTMLElement): void { + super.render(container); + ++ if (this._keybinding) {","@RohithKumbharkar I have a different suggestion where to put this code that makes it much easier. If you look below in that class there is a `public set keybinding(keybinding: string)`. I suggest to set the title in there because it gets computed there: + +```typescript +this.$label.title(title); +this.$badge.title(title); +this.$container.title(title); // <-- add it here +```",2017-06-15 15:50:28 +572,"@@ -310,7 +310,7 @@ class DecorationRenderHelper { + cssTextArr.push(strings.format(this._CSS_MAP.contentIconPath, opts.contentIconPath.toString(true).replace(/'/g, '%27')));","What is the reason for this change? +How can we be sure that we did not break any of the many use cases editor decorations have. + +This PR should not touch anything in the editor land. A change in the editor land is only acceptable if there is no alternative.",2016-12-05 14:48:24 +898,"@@ -310,7 +310,7 @@ export class ExtHostSCM { + return sourceControl; + } + +- $provideOriginalResource(sourceControlHandle: number, uri: URI): TPromise {","I also wasn't entirely sure of `URI` vs `vscode.Uri`. I think the change itself is correct, but I was not confident to know if any existing code is relying on the old signature or if this change could cause any trouble",2017-04-24 23:50:46 +515,"@@ -312,7 +312,10 @@ export class DebugService implements debug.IDebugService { + })); + + this.toDisposeOnSessionEnd[session.getId()].push(session.onDidContinued(event => { +- this.transitionToRunningState(session, event.body.allThreadsContinued ? undefined : event.body.threadId); ++ // TODO: This calls onStackFrame with null stack frame on every step causing all decorators to be re-drawn. ++ // onDidContinued also gets called for step-over causing flash in decorators due to removeDecorators and setDecorators call ++ // One idea is to use throttled onStackFrame, other is to only call onDidContinued only for continue ++ // this.transitionToRunningState(session, event.body.allThreadsContinued ? undefined : event.body.threadId); + }));","Let's first try with the idea I mentioned in my comment - to use editor.deltaDecorations and keep track of our decorations. +Calling onDidContinued only for continue will not work because some step calls can take arbitrary long, so in essence they can be just like a continue. + +If the decoraionts idea does not work then we will update decorations with a delay, similar to how the debug views in the debug viewlet have a delay to prevetn tree collapsing and flashing",2016-11-28 10:22:48 +977,"@@ -316,6 +321,29 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + etag = this.lastResolvedDiskStat.etag; // otherwise respect etag to support caching + } + ++ const storageKey = 'workbench.tasks.ranTaskBefore';",Can you put this in its own method?,2017-06-16 20:13:11 +271,"@@ -317,10 +322,10 @@ export class TerminalService implements ITerminalService { + return terminalProcess; + } + +- public static createTerminalEnv(parentEnv: IStringDictionary, shell: IShell, workspace: IWorkspace, locale?: string): IStringDictionary { ++ public static createTerminalEnv(parentEnv: IStringDictionary, shell: IShell, workspace: IWorkspace, shellPath?: string, locale?: string): IStringDictionary {","Thinking about this again, I think we should probably support args for the shellPath too (what `IShell` does). Meaning shellPath and shellArgs should pass through the API layers. +",2016-09-08 19:07:24 +104,"@@ -319,6 +341,9 @@ export class WorkingFilesModel implements IWorkingFilesModel { + } + + public clear(): void { ++ this.recentlyClosedEntries.push(this.entries.map((entry) => { ++ return entry.resource; ++ }));","This should just shift all entries into the array of recently closed entries. +",2016-04-09 14:44:34 +996,"@@ -319,7 +324,57 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + // Resolve Content + return this.textFileService + .resolveTextContent(this.resource, { acceptTextOnly: true, etag, encoding: this.preferredEncoding }) +- .then(content => this.handleLoadSuccess(content), error => this.handleLoadError(error)); ++ .then(content => this.handleLoadSuccess(content), error => this.handleLoadError(error)) ++ .then((result) => { ++ this.showTaskNotification(); ++ return result; ++ }); ++ } ++ ++ private showTaskNotification(): void { ++ const storageKey = 'workbench.tasks.ranTaskBefore'; ++ if (this.storageService.get(storageKey)) { ++ const fileName = path.relative(this.contextService.getWorkspace().resource.toString(), this.resource.toString()); ++ if (fileName.match(/^gruntfile\.js$/i) || fileName.match(/^gulpfile\.js$/i) || fileName.match(/^tsconfig\.json$/i)) { ++ const message = localize('taskFileOpened', `Run your ${fileName.split('.')[0]} in vscode. Get started here.`); ++ let action: any; ++ let messageTest: string; ++ const showDocumentation = isShowTaskDocumentation(this.storageService);",You can use `telemetryService.getExperiments().showTaskDocumentation` instead.,2017-06-19 22:00:12 +66,"@@ -319,71 +319,71 @@ export const HTML_TAGS: ITagSet = { + }; + + export const IONIC_TAGS: ITagSet = { +- 'ion-checkbox': new HTMLTagSpecification('', ++ 'ion-checkbox': new HTMLTagSpecification(nls.localize('tags.ion.checkbox', 'The checkbox is no different than the HTML checkbox input, except it\'s styled differently. The checkbox behaves like any AngularJS checkbox.'),","I've used nls.localize, with a string ID for each label; is there anything else to do for localization? +",2016-03-04 21:54:55 +895,"@@ -32,5 +32,6 @@ + ""typescript.implementationsCodeLens.enabled"": ""Enable/disable implementations CodeLens. Requires TypeScript >= 2.2.0."", + ""typescript.openTsServerLog.title"": ""Open TS Server log file"", + ""typescript.selectTypeScriptVersion.title"": ""Select TypeScript Version"", +- ""jsDocCompletion.enabled"": ""Enable/disable auto JSDoc comments"" ++ ""jsDocCompletion.enabled"": ""Enable/disable auto JSDoc comments"", ++ ""javascript.implicitProjectConfig.checkJs"": ""Enable/disable type checking in loose JavaScript files that are not included in any jsconfig or tsconfig projects. Requires TypeScript >= 2.3.1.""","I'm still not sure how to clearly express when this setting applies and when it does not + +The setting applies only when a javascript file is not included in a JavaScript project as defined in a `jsconfig` or `tsconfig`. If the file is part of a project, the user must instead enable `checkJs` in the config file itself + +@kieferrm Let me know if you have any suggestions here",2017-04-21 03:04:44 +549,"@@ -32,6 +32,7 @@ export interface IWindowCreationOptions { + extensionDevelopmentPath?: string; + allowFullscreen?: boolean; + titleBarStyle?: 'native' | 'custom'; ++ vscodeWindowId?: string;",@Tyriar I would suggest to call this `id` and instead fix all users of the current `id` property to use `vscodeWindows.win.id` because that makes it very clear what ID is being asked.,2016-12-01 16:20:32 +905,"@@ -32,7 +32,7 @@ class JsDocCompletionItem extends CompletionItem { + ) { + super('/** */', CompletionItemKind.Snippet); + this.detail = localize('typescript.jsDocCompletionItem.documentation', 'JSDoc comment'); +- this.insertText = ''; ++ this.insertText = ' ';","This is the minimal change that fixes the issue. I also considered updating the suggestion provider to not apply the new enter logic for empty insert text or for completions with commands, however this carried more risk. + +I'm also going to try to get TypeScript to improve the api we use to get doctemplates so that the `JsDocCompletionItem` doesn't require using a command",2017-05-05 05:10:15 +150,"@@ -32,7 +32,7 @@ var baseModules = [ + 'applicationinsights', 'assert', 'child_process', 'chokidar', 'crypto', 'emmet', + 'events', 'fs', 'getmac', 'glob', 'graceful-fs', 'http', 'http-proxy-agent', + 'https', 'https-proxy-agent', 'iconv-lite', 'electron', 'net', +- 'os', 'path', 'readline', 'sax', 'semver', 'stream', 'string_decoder', 'url', ++ 'os', 'path', 'pty.js', 'readline', 'sax', 'semver', 'stream', 'string_decoder', 'url', 'term.js',","Is this change related to 3077? +",2016-05-20 08:18:13 +979,"@@ -321,12 +321,21 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + etag = this.lastResolvedDiskStat.etag; // otherwise respect etag to support caching + } + ++ this.taskNotification();","Maybe this should only happen after opening the file succeeds? Partly to avoid slowing down the file open with extra work, but also, a file can fail to open, in which case you don't want to show the notification. ",2017-06-16 23:28:40 +980,"@@ -321,12 +321,21 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + etag = this.lastResolvedDiskStat.etag; // otherwise respect etag to support caching + } + ++ this.taskNotification(); ++ ++ // Resolve Content ++ return this.textFileService ++ .resolveTextContent(this.resource, { acceptTextOnly: true, etag, encoding: this.preferredEncoding }) ++ .then(content => this.handleLoadSuccess(content), error => this.handleLoadError(error)); ++ } ++ ++ private taskNotification(): void {",More verb-y name like `showTaskNotification` or something,2017-06-16 23:29:07 +978,"@@ -321,12 +321,21 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + etag = this.lastResolvedDiskStat.etag; // otherwise respect etag to support caching + } + ++ this.taskNotification(); ++ ++ // Resolve Content ++ return this.textFileService ++ .resolveTextContent(this.resource, { acceptTextOnly: true, etag, encoding: this.preferredEncoding }) ++ .then(content => this.handleLoadSuccess(content), error => this.handleLoadError(error)); ++ } ++ ++ private taskNotification(): void { + const storageKey = 'workbench.tasks.ranTaskBefore'; +- const fileName = path.relative(this.storageService['workspaceKey'], this.resource['_formatted']); ++ const fileName = path.relative(this.contextService.getWorkspace().resource.toString(), this.resource.toString());","Can you only do this check if the storageService check succeeds, to avoid extra work, since most of the time, it won't be needed?",2017-06-16 23:25:56 +835,"@@ -323,6 +323,10 @@ export class RawDebugSession extends v8.V8Protocol implements debug.ISession { + return this.send('stackTrace', args);",Looks good,2017-03-21 17:01:11 +856,"@@ -323,6 +323,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ShowEditorsInGroupThre + registry.registerWorkbenchAction(new SyncActionDescriptor(OpenNextEditor, OpenNextEditor.ID, OpenNextEditor.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.PageDown, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET] } }), 'View: Open Next Editor', category); + registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousEditor, OpenPreviousEditor.ID, OpenPreviousEditor.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.PageUp, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_OPEN_SQUARE_BRACKET] } }), 'View: Open Previous Editor', category); + registry.registerWorkbenchAction(new SyncActionDescriptor(ReopenClosedEditorAction, ReopenClosedEditorAction.ID, ReopenClosedEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_T }), 'View: Reopen Closed Editor', category); ++registry.registerWorkbenchAction(new SyncActionDescriptor(ClearRecentItemsAction, ClearRecentItemsAction.ID, ClearRecentItemsAction.LABEL), 'View: Clear Items', category);",`Clear Recent Files` maybe?,2017-03-23 14:06:25 +15,"@@ -325,7 +325,7 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { + + private static FOCUSED_STACK_FRAME_DECORATION: editorcommon.IModelDecorationOptions = { + isWholeLine: true, +- className: 'debug-focussed-stack-frame-line', ++ className: 'debug-focused-stack-frame-line',","Make sure you adopt the same change on `src/vs/workbench/parts/debug/browser/media/debug.contribution.css` where this class name is used. +",2015-11-25 08:35:38 +784,"@@ -327,20 +327,14 @@ export class Repository { + return TPromise.wrapError(localize('errorBuffer', ""Can't open file from git"")); + } + +- return new Promise((c, e) => { +- detectMimesFromStream(child.stdout, null, (err, result) => { +- if (err) { +- e(err); +- } else if (isBinaryMime(result.mimes)) { +- e({ +- message: localize('fileBinaryError', ""File seems to be binary and cannot be opened as text""), +- fileOperationResult: FileOperationResult.FILE_IS_BINARY +- }); +- } else { +- c(this.doBuffer(object)); +- } +- }); +- }); ++ return detectMimesFromStream(child.stdout, null).then(result => ++ isBinaryMime(result.mimes) ? ++ TPromise.wrapError({",@katainaka0503 return missing here?,2017-03-01 09:18:16 +783,"@@ -328,7 +328,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient + } + + private get bundledTypeScriptPath(): string { +- return path.join(__dirname, '..', 'node_modules', 'typescript', 'lib', 'tsserver.js'); ++ return path.join(__dirname, '..', '..', 'node_modules', 'typescript', 'lib', 'tsserver.js');",Use `require.resolve('typescript/lib/tsserver.js')` instead to avoid the path dependency,2017-03-01 08:26:39 +960,"@@ -329,16 +329,20 @@ export function createApiFactory( + return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables); + }, + showInformationMessage(message, first, ...rest) { +- return extHostMessageService.showMessage(Severity.Info, message, first, rest);",These changes are the main ones I'm uncertain about. Let me know if you think a different fix would be better,2017-06-06 19:00:04 +837,"@@ -33,15 +33,40 @@ export class ExceptionWidget extends ZoneWidget { + const fontInfo = this.editor.getConfiguration().fontInfo; + this.container.style.fontSize = `${fontInfo.fontSize}px`; + this.container.style.lineHeight = `${fontInfo.lineHeight}px`; +- +- let title = $('.title'); +- title.textContent = nls.localize('exceptionThrown', 'Exception occurred'); +- dom.append(container, title); +- + const thread = this.debugService.getViewModel().focusedThread; ++ + if (thread && thread.stoppedDetails) { ++ let title = $('.title'); + let msg = $('.message'); +- msg.textContent = thread.stoppedDetails.text; ++ ++ if (this.exceptionInfo) { ++ let conditionMessage; ++ switch (this.exceptionInfo.body.breakMode) { ++ case 'never': ++ conditionMessage = nls.localize('neverException', 'User-handled exception has occurred.'); ++ break; ++ case 'always': ++ conditionMessage = nls.localize('alwaysException', 'Always-breaking exception has occurred.'); ++ break; ++ case 'unhandled': ++ conditionMessage = nls.localize('unhandledException', 'Unhandled exception has occurred.'); ++ break; ++ case 'userUnhandled': ++ conditionMessage = nls.localize('userUnhandledException', 'User-unhandled exception has occurred.'); ++ break; ++ default: ++ conditionMessage = '';",I would prefer if the default case had the same `Exception occurred` message as the case when there is no exceptionInfo,2017-03-21 17:04:00 +838,"@@ -33,15 +33,40 @@ export class ExceptionWidget extends ZoneWidget { + const fontInfo = this.editor.getConfiguration().fontInfo; + this.container.style.fontSize = `${fontInfo.fontSize}px`; + this.container.style.lineHeight = `${fontInfo.lineHeight}px`; +- +- let title = $('.title'); +- title.textContent = nls.localize('exceptionThrown', 'Exception occurred'); +- dom.append(container, title); +- + const thread = this.debugService.getViewModel().focusedThread; ++ + if (thread && thread.stoppedDetails) { ++ let title = $('.title'); + let msg = $('.message'); +- msg.textContent = thread.stoppedDetails.text; ++ ++ if (this.exceptionInfo) { ++ let conditionMessage; ++ switch (this.exceptionInfo.body.breakMode) { ++ case 'never': ++ conditionMessage = nls.localize('neverException', 'User-handled exception has occurred.'); ++ break; ++ case 'always': ++ conditionMessage = nls.localize('alwaysException', 'Always-breaking exception has occurred.'); ++ break; ++ case 'unhandled': ++ conditionMessage = nls.localize('unhandledException', 'Unhandled exception has occurred.'); ++ break; ++ case 'userUnhandled': ++ conditionMessage = nls.localize('userUnhandledException', 'User-unhandled exception has occurred.'); ++ break; ++ default: ++ conditionMessage = ''; ++ break; ++ } ++ ++ title.textContent = `${conditionMessage} ${this.exceptionInfo.body.description}`;",You are missing a colon here between the condition message and the description,2017-03-21 17:04:17 +506,"@@ -33,4 +36,42 @@ const extensions = [ + 'html' + ]; + +-extensions.forEach(extension => npmInstall(`extensions/${extension}`)); +\ No newline at end of file ++extensions.forEach(extension => npmInstallSync(`extensions/${extension}`)); ++ ++function rmDuplicateModulesSync() { ++ ++ function fetchModuleIds(basepath) { ++ const result = new Map(); ++ for (const candidate of fs.readdirSync(path.join(basepath, 'node_modules'))) { ++ try { ++ let raw = fs.readFileSync(path.join(basepath, 'node_modules', candidate, 'package.json')); ++ let data = JSON.parse(raw); ++ result.set(data._id, path.join(basepath, 'node_modules', candidate)); ++ } catch (e) { ++ if (e.code !== 'ENOENT') { ++ throw e; ++ } ++ } ++ } ++ return result; ++ } ++ ++ const duplicates = new Set(); ++ const baseModules = fetchModuleIds(''); ++ ++ for (const extension of extensions) { ++ const extensionModules = fetchModuleIds(`extensions/${extension}`); ++ for (let [key, value] of extensionModules) { ++ if (baseModules.has(key)) { ++ duplicates.add(value); ++ } ++ } ++ } ++ ++ for (let duplicate of duplicates) { ++ console.log(`REMOVING duplicate module '${duplicate}'`); ++ rimraf.sync(path.join(process.cwd(), duplicate));",Is `process.cwd()` a good idea here?,2016-11-23 18:16:59 +811,"@@ -331,6 +331,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(CloseEditorsInGroupAct + registry.registerWorkbenchAction(new SyncActionDescriptor(CloseOtherEditorsInGroupAction, CloseOtherEditorsInGroupAction.ID, CloseOtherEditorsInGroupAction.LABEL, { primary: null, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_T } }), 'View: Close Other Editors', category); + registry.registerWorkbenchAction(new SyncActionDescriptor(CloseEditorsInOtherGroupsAction, CloseEditorsInOtherGroupsAction.ID, CloseEditorsInOtherGroupsAction.LABEL), 'View: Close Editors in Other Groups', category); + registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorAction, SplitEditorAction.ID, SplitEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH }), 'View: Split Editor', category); ++registry.registerWorkbenchAction(new SyncActionDescriptor(JoinEditorsAction, JoinEditorsAction.ID, JoinEditorsAction.LABEL), 'View: Join Editors', category);",Should this maybe be more descriptive to what it actually does? `Join Editors of two Groups`?,2017-03-10 14:23:11 +998,"@@ -333,23 +333,44 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + + private showTaskNotification(): void { + const storageKey = 'workbench.tasks.ranTaskBefore'; +- if (!this.storageService.get(storageKey)) { ++ if (this.storageService.get(storageKey)) { + const fileName = path.relative(this.contextService.getWorkspace().resource.toString(), this.resource.toString()); + if (fileName.match(/^gruntfile\.js$/i) || fileName.match(/^gulpfile\.js$/i) || fileName.match(/^tsconfig\.json$/i)) { +- const message = localize('taskFileOpened', ""Visual Studio Code has extra functionality for this type of file""); +- const action = this.instantiationService.createInstance(ShowTasksAction, ShowTasksAction.ID, localize('showTasks', ""Show Tasks"")); +- ++ const message = localize('taskFileOpened', `Run your ${fileName.split('.')[0]} in vscode. Get started here.`);","This is going to fail the main build, or not work - localized strings have to be constant string literals. But you can add a placeholder like this: + +`localize('id', 'foo {0} bar {1}', 'string inserted at {0}', 'inserted at {1}' ...)`",2017-06-19 22:09:18 +999,"@@ -333,23 +333,44 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + + private showTaskNotification(): void { + const storageKey = 'workbench.tasks.ranTaskBefore'; +- if (!this.storageService.get(storageKey)) { ++ if (this.storageService.get(storageKey)) { + const fileName = path.relative(this.contextService.getWorkspace().resource.toString(), this.resource.toString()); + if (fileName.match(/^gruntfile\.js$/i) || fileName.match(/^gulpfile\.js$/i) || fileName.match(/^tsconfig\.json$/i)) { +- const message = localize('taskFileOpened', ""Visual Studio Code has extra functionality for this type of file""); +- const action = this.instantiationService.createInstance(ShowTasksAction, ShowTasksAction.ID, localize('showTasks', ""Show Tasks"")); +- ++ const message = localize('taskFileOpened', `Run your ${fileName.split('.')[0]} in vscode. Get started here.`); ++ let action: any;",Type as `Action` instead of `any`,2017-06-19 22:13:18 +108,"@@ -333,6 +346,27 @@ export class WorkingFilesModel implements IWorkingFilesModel { + return this.mapEntryToResource[resource.toString()]; + } + ++ private recordRecentlyClosedEntries(resources: WorkingFileEntry[]): void { ++ if (resources.length === 0) { ++ return; ++ } ++ ++ // Make the active entry the first entry","@Tyriar can you explain what these lines are for? +",2016-04-15 06:23:01 +890,"@@ -334,6 +335,22 @@ export class VSCodeWindow { + return this._readyState; + } + ++ private registerNavigationListenerOn(command: string, back: string, forward: string) { ++ this._win.on(command, (e, cmd) => { ++ if (this.readyState !== ReadyState.READY) { ++ return; // window must be ready ++ } ++ ++ if (cmd === back) { ++ this.send('vscode:runAction', 'workbench.action.navigateBack'); ++ } else if (cmd === forward) { ++ this.send('vscode:runAction', 'workbench.action.navigateForward'); ++ } else { ++ console.warn('[electron command]: did not handle: ', command);","Should not happen, please remove.",2017-04-18 05:51:48 +481,"@@ -334,6 +356,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + diag('makeDirty() - prevented save because we are in conflict resolution mode', this.resource, new Date()); + } + } ++ ++ // Trigger listeners only if no auto save occurred and model changes were not blocked ++ this._onDidContentChange.fire();","@Tyriar hm careful here. there are some return statements above e.g. when the user undos his changes up to the saved version, don't we want to also update (or actually discard) the backup in that case? + +Also I am not sure the comment `if no auto save occurred` makes sense. +",2016-11-09 07:59:48 +359,"@@ -339,6 +339,17 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic + this.recentlyClosedFiles = []; + } + ++ public block(block: boolean) { ++ if (block) { ++ this.blockStackChanges = true; ++ this.blockEditorHistoryChanges = true; ++ }","@wprater style, prefer `} else {` +",2016-10-21 09:52:52 +380,"@@ -339,6 +346,15 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal + + // Activity Bar + let activityBarMinWidth = this.computedStyles.activitybar.minWidth; ++ ++ // For inline titles, we want to ignore the minWidth on the activity bar ++ // and generate a zoom-dependent width, to ensure all other parts lay out correctly ++ const windowConfig = this.configurationService.getConfiguration(); ++ if (windowConfig && windowConfig.window.macOSUseInlineToolbar) { ++ const zoom = webFrame.getZoomFactor(); ++ activityBarMinWidth = 76/zoom;","@orta the 76px should be read from the CSS file if possible and not hardcoded (compare with https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/browser/layout.ts#L307) +",2016-10-23 06:53:05 +325,"@@ -339,7 +339,11 @@ export interface IAskpassService { + } + + // Utils ++const invalidBranchPatternName = /(^\.)|(\/\.)|(\.\.)|(~)|(\^)|(:)|(\/$)|(\.lock$)|(\.lock\/)|(\\)|(\*)|(\s)|(^\s*$)|(\.$)/g;","Why wrapping everything in groups? The regex is now broken since the `^` and `$` were making sure the whole string is matched. +",2016-10-14 12:51:15 +596,"@@ -34,7 +34,18 @@ export default class TypeScriptDocumentHighlightProvider implements DocumentHigh + } + return this.client.execute('occurrences', args, token).then((response): DocumentHighlight[] => { + let data = response.body; +- if (data) { ++ if (data && data.length) {","We may also want to scope to using the TypeScript version just to be safe. That way if something does go terribly wrong, users could point to their own ts install as a workaround.",2016-12-12 18:13:18 +158,"@@ -340,4 +341,11 @@ suite('Sass - Sass Parser', () => { + assertNode('%hover', parser, parser._parseSimpleSelector.bind(parser)); + assertNode('a%float', parser, parser._parseSimpleSelector.bind(parser)); + }); ++ ++ test('Sass Parser - Css Variable Declaration', function() {","Just one tiny suggestion, we may want to use `CSS` or `css` rather than `Css` +",2016-05-20 17:25:00 +423,"@@ -340,6 +342,9 @@ export function createApiFactory(initDataConfiguration: IInitConfiguration, init + onWillSaveTextDocument: (listener, thisArgs?, disposables?) => { + return extHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables); + }, ++ registerTreeExplorerNodeProvider(providerId: string, provider: vscode.TreeExplorerNodeProvider) {","[needs change] This function must be marked as proposed - look at the [`sampleFunction`](https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/api/node/extHost.api.impl.ts#L279) +",2016-11-01 09:40:02 +25,"@@ -342,7 +341,15 @@ export const Suggest = { + result.documentation = suggestion.documentationLabel; + result.sortText = suggestion.sortText; + result.filterText = suggestion.filterText; +- result.textEdit = suggestion.textEdit && TextEdit.to(suggestion.textEdit); ++ ++ var overwriteBefore = (typeof suggestion.overwriteBefore !== 'undefined') ? suggestion.overwriteBefore : container.currentWord.length;","boh, `var` +",2015-12-11 10:24:44 +614,"@@ -3422,17 +3423,18 @@ declare module 'vscode' { + * register a command handler with the identfier `extension.sayHello`. + * ```javascript + * commands.registerCommand('extension.sayHello', () => { +- * window.showInformationMessage('Hello World!'); ++ * window.showInformationMessage('Hello World!'); + * }); + * ``` + * Second, bind the command identfier to a title under which it will show in the palette (`package.json`). + * ```json + * { +- * ""contributes"": { +- * ""commands"": [{ +- * ""command"": ""extension.sayHello"", +- * ""title"": ""Hello World"" +- * }] ++ * ""contributes"": { ++ * ""commands"": [{ ++ * ""command"": ""extension.sayHello"", ++ * ""title"": ""Hello World"" ++ * }] ++ * }",This one seemed to be missing a closing curly brace,2016-12-15 23:50:29 +251,"@@ -3429,6 +3460,15 @@ declare namespace vscode { + * @return A new status bar item. + */ + export function createStatusBarItem(alignment?: StatusBarAlignment, priority?: number): StatusBarItem; ++ ++ /** ++ * Creates a [Terminal](#Terminal). ++ * ++ * @param name The optional name of a terminal, this will override the label used in the ++ * terminal dropdown. ++ * @return A new Terminal. ++ */ ++ export function createTerminal(name?: string): Thenable;","We do not return promises from there functions but already working objects (see `createStatusBarItem`). It should be `createTerminal(name?: string): Terminal`. We don't expose in the API that stuff is being created/executed in a different process. +",2016-08-18 19:28:17 +554,"@@ -344,3 +366,49 @@ interface CacheStats { + cacheFilterStartTime: number; + cacheFilterResultCount: number; + } ++ ++/** ++ * Collects a batch of items that each have a size. When the cumulative size of the batch reaches 'maxBatchSize', it calls the callback. ++ * If the batch isn't filled within 'timeout' ms, the callback is also called. ++ * And after 'batchOnlyAfter' items, the timeout is ignored, and the callback is called only when the batch is full.","`batchOnlyAfter` seems misleading, we batch before too.",2016-12-01 18:50:42 +555,"@@ -344,3 +366,49 @@ interface CacheStats { + cacheFilterStartTime: number; + cacheFilterResultCount: number; + } ++ ++/** ++ * Collects a batch of items that each have a size. When the cumulative size of the batch reaches 'maxBatchSize', it calls the callback. ++ * If the batch isn't filled within 'timeout' ms, the callback is also called. ++ * And after 'batchOnlyAfter' items, the timeout is ignored, and the callback is called only when the batch is full. ++ */ ++class BatchedCollector { ++ private totalNumberCompleted = 0; ++ private batch: T[] = []; ++ private batchSize = 0; ++ private timeoutHandle: number; ++ ++ constructor(private maxBatchSize: number, private timeout: number, private batchOnlyAfter: number, private cb: (items: T | T[]) => void) { ++ } ++ ++ addItem(item: T, size: number): void { ++ if (!item) { ++ return; ++ } ++ ++ if (this.maxBatchSize > 0) { ++ this.batch.push(item); ++ this.batchSize += size; ++ if (this.batchSize >= this.maxBatchSize) { ++ this.flush(); ++ } else { ++ if (!this.timeoutHandle && this.totalNumberCompleted < this.batchOnlyAfter) { ++ this.timeoutHandle = setTimeout(() => { ++ this.flush(); ++ }, this.timeout); ++ } ++ } ++ } else { ++ this.cb(item); ++ } ++ } ++ ++ flush(): void { ++ this.totalNumberCompleted += this.batchSize;",Check if `this.batchSize > 0`?,2016-12-01 18:52:02 +737,"@@ -346,8 +346,10 @@ class MouseDownOperation extends Disposable { + + private _mouseMoveMonitor: GlobalEditorMouseMoveMonitor; + private _mouseDownThenMoveEventHandler: EventGateKeeper; ++ private _mouseDragThenMoveEventHandler: EventGateKeeper;","No need for a separate handler, I suggest to use `mouseState.lastMouseDownEvent` (which should be renamed to something better, see other comment) to differentiate the two cases inside `onMouseDownThenMove`",2017-02-20 11:07:43 +273,"@@ -347,4 +352,19 @@ export class TerminalService implements ITerminalService { + } + return parts.join('_') + '.UTF-8'; + } ++} ++ ++interface ITerminalProcessConfiguration { ++ _name: string;","Underscore not necessary since it's public +",2016-09-08 19:11:24 +272,"@@ -347,4 +352,19 @@ export class TerminalService implements ITerminalService { + } + return parts.join('_') + '.UTF-8'; + } ++} ++ ++interface ITerminalProcessConfiguration { ++ _name: string; ++ _shellPath: string; ++} ++ ++class TerminalProcessConfiguration implements ITerminalProcessConfiguration {","We don't really need to implement the interface, an interface is all we need to enforce the types. TypeScript allows regular objects `{}` to use interfaces and keeps the type safe. +",2016-09-08 19:08:23 +675,"@@ -349,6 +349,18 @@ export class TabsTitleControl extends TitleControl { + tabContainer.setAttribute('role', 'presentation'); // cannot use role ""tab"" here due to https://github.com/Microsoft/vscode/issues/8659 + DOM.addClass(tabContainer, 'tab monaco-editor-background'); + ++ if (!this.tabOptions.showTabCloseButton || this.tabOptions.tabCloseButton === 'off') {",Please move this into the `doUpdate` method above where you will notice that there already is an update for `no-close-button` class from the other option (that should be deleted). We need to have it there because otherwise tabs will not update live from a config change.,2017-01-16 07:59:36 +268,"@@ -3497,9 +3497,10 @@ declare namespace vscode { + * [Terminal.show](#Terminal.show) in order to show the terminal panel. + * + * @param name Optional human-readable string which will be used to represent the terminal in the UI. ++ * @param shellPath Path to the user-requested shell executable that will be used in the terminal","Change this to: + +> @param shellPath Optional path to a custom shell executable to be used in the terminal. +",2016-09-08 18:53:00 +329,"@@ -35,6 +35,10 @@ + + /** Custom Mac Cursor */ + ++.monaco-workbench.mac.use-inline-toolbar > .monaco-sash.mac {","We should not add workbench dependencies here, instead if we want to override something for widgets it should go into workbench.css +",2016-10-15 06:14:13 +931,"@@ -358,6 +358,7 @@ export class ManageExtensionAction extends Action { + instantiationService.createInstance(EnableGloballyAction, localize('enableAlwaysAction.label', ""Enable (Always)"")) + ], + [ ++ instantiationService.createInstance(AddToWorkspaceRecommendationsAction, localize('addToWorkspaceRecommendationsAction.label', ""Add to Workspace Recommendations"")),","How about having a short label - `Recommend (Workspace)` and `Unrecommend (Workspace)`. Not sure `Workspace` word is necessary since a user can recommend only to Workspace, but having it makes it complete.",2017-05-12 09:14:36 +876,"@@ -3646,6 +3646,18 @@ declare module 'vscode' { + export function showTextDocument(document: TextDocument, column?: ViewColumn, preserveFocus?: boolean): Thenable; + + /** ++ * Show the given document in a text editor. A [column](#ViewColumn) can be provided ++ * to control where the editor is being shown. Might change the [active editor](#window.activeTextEditor). ++ * ++ * @param document A text document to be shown. ++ * @param column A view column in which the editor should be shown. The default is the [one](#ViewColumn.One), other values ++ * are adjusted to be __Min(column, columnCount + 1)__. ++ * @param options Editor options for showing the text editor. ++ * @return A promise that resolves to an [editor](#TextEditor). ++ */ ++ export function showTextDocument(document: TextDocument, column?: ViewColumn, options?: { preserveFocus?: boolean, pinned?: boolean }): Thenable;","Sooo, if we add this new overload it should include `column` and also make it a type which we can document nicer",2017-04-13 15:13:46 +467,"@@ -369,6 +373,30 @@ export class WindowsManager implements IWindowsMainService, IWindowEventService + iPathsToOpen = this.cliToPaths(openConfig.cli, ignoreFileNotFound); + } + ++ let configuration: IWindowConfiguration;","@Tyriar suggest to move this code block down before the line + +`// Handle files to open/diff or to create when we dont open a folder` + +Because there we actually start the job of opening something. +",2016-11-09 07:21:08 +466,"@@ -369,6 +373,30 @@ export class WindowsManager implements IWindowsMainService, IWindowEventService + iPathsToOpen = this.cliToPaths(openConfig.cli, ignoreFileNotFound); + } + ++ let configuration: IWindowConfiguration; ++ let openInNewWindow = openConfig.preferNewWindow || openConfig.forceNewWindow; ++ ++ // Restore any existing backup workspaces ++ if (openConfig.restoreBackups) { ++ const workspacesWithBackups = this.backupService.getWorkspaceBackupPathsSync();","@Tyriar again not sure about all the sync fs calls are needed here +",2016-11-09 07:20:33 +322,"@@ -37,6 +38,7 @@ export class DirtyFilesTracker implements IWorkbenchContribution { + + constructor( + @ITextFileService private textFileService: ITextFileService, ++ @IFileService private fileService: IFileService,","Unused service? +",2016-10-13 15:13:31 +479,"@@ -370,9 +374,9 @@ export abstract class TextFileService implements ITextFileService { + return this._models.getAll(arg1); + } + +- private getDirtyFileModels(resources?: URI[]): ITextFileEditorModel[]; +- private getDirtyFileModels(resource?: URI): ITextFileEditorModel[]; +- private getDirtyFileModels(arg1?: any): ITextFileEditorModel[] { ++ public getDirtyFileModels(resources?: URI[]): ITextFileEditorModel[];","@Tyriar why public here? not used outside it seems +",2016-11-09 07:57:00 +901,"@@ -373,15 +376,31 @@ export function registerCommands(): void { + win: { primary: void 0 } + }); + +- CommandsRegistry.registerCommand('_workbench.diff', function (accessor: ServicesAccessor, args: [URI, URI, string, string]) { ++ CommandsRegistry.registerCommand('_workbench.diff', function (accessor: ServicesAccessor, args: [URI, URI, string, string, vscode.TextDocumentShowOptions]) {",it's dangerous to use the vscode-module here (actually everywhere outside the extension host) because these type actually don't exist. for interfaces it's OK because they disappear but using `IEditorOption` would have been better,2017-04-25 13:58:11 +867,"@@ -373,6 +373,19 @@ export class VSCodeWindow { + } + }); + ++ // Swipe command support (macOS) ++ this._win.on('swipe', (e, cmd) => {",@seivan can we reuse this code with the `on('app-command')` handler? Seems duplicate.,2017-03-30 23:08:19 +961,"@@ -375,3 +390,26 @@ CommonEditorRegistry.registerEditorCommand(new SuggestCommand({ + primary: KeyCode.RightArrow + } + })); ++ ++@editorAction ++class ReplCopyAllAction extends EditorAction { ++ ++ constructor() { ++ super({ ++ id: 'repl.action.copyall', ++ label: nls.localize('actions.repl.copyall', ""Debug Copy All""),","I would prefer the title to be ""Debug: Console Copy All"", that way it nicely aligns with the other debug actions and has a more clear name",2017-06-08 09:56:50 +962,"@@ -375,3 +390,26 @@ CommonEditorRegistry.registerEditorCommand(new SuggestCommand({ + primary: KeyCode.RightArrow + } + })); ++ ++@editorAction ++class ReplCopyAllAction extends EditorAction { ++ ++ constructor() { ++ super({ ++ id: 'repl.action.copyall', ++ label: nls.localize('actions.repl.copyall', ""Debug Copy All""), ++ alias: 'Debug Copy All', ++ precondition: debug.CONTEXT_IN_DEBUG_REPL, ++ kbOpts: {","I think you can just leave out the `kbOpts` and it should nicely compile, please try that",2017-06-08 09:58:02 +489,"@@ -376,6 +380,28 @@ export class WindowsManager implements IWindowsMainService { + } + + let configuration: IWindowConfiguration; ++ let openInNewWindow = openConfig.preferNewWindow || openConfig.forceNewWindow; ++ ++ // Restore any existing backup workspaces ++ if (openConfig.restoreBackups) { ++ const workspacesWithBackups = this.backupService.getWorkspaceBackupPaths(); ++ ++ workspacesWithBackups.forEach(workspacePath => { ++ if (!fs.existsSync(workspacePath)) {","@Tyriar would it be possible that we have a backup workspace without backups to restore? maybe we should add more checks here that a backup workspace path should only cause a window to open if it has backups, otherwise it gets deleted. I am thinking of situations where we the backup workspace gets out of sync with the backups within (for whatever reason - e.g. crash). This would prevent bugs where multiple windows just open even though there are no backups. +",2016-11-15 05:56:16 +491,"@@ -376,6 +380,28 @@ export class WindowsManager implements IWindowsMainService { + } + + let configuration: IWindowConfiguration; ++ let openInNewWindow = openConfig.preferNewWindow || openConfig.forceNewWindow; ++ ++ // Restore any existing backup workspaces ++ if (openConfig.restoreBackups) { ++ const workspacesWithBackups = this.backupService.getWorkspaceBackupPaths(); ++ ++ workspacesWithBackups.forEach(workspacePath => { ++ if (!fs.existsSync(workspacePath)) { ++ this.backupService.removeWorkspaceBackupPathSync(Uri.file(workspacePath)); ++ return; ++ } ++ ++ const untitledToRestore = this.backupService.getWorkspaceUntitledFileBackupsSync(Uri.file(workspacePath)).map(filePath => {","@Tyriar same comment here about how to restore untitled files. This would not be needed if untitled had input factory. +",2016-11-15 05:59:45 +78,"@@ -378,6 +424,14 @@ export class Model extends ee.EventEmitter implements debug.IModel { + this.emit(debug.ModelEvents.CALLSTACK_UPDATED); + } + ","Should `continueThreads()` also `clearCallstack()` for each `thread`? +",2016-03-16 10:44:40 +697,"@@ -3801,6 +3810,13 @@ export interface ICommonCodeEditor extends IEditor { + onDidType(listener: (text: string) => void): IDisposable; + + /** ++ * An event emitted when users paste text in the editor. ++ * @event ++ * @internal ++ */ ++ onDidPaste(listener: (range: Range) => void): IDisposable;","Here we say we give out a `Range`, but the implementation gives out an `IRange`. Please adjust the implementation.",2017-01-19 15:38:39 +399,"@@ -3804,6 +3870,15 @@ declare module 'vscode' { + export function registerTextDocumentContentProvider(scheme: string, provider: TextDocumentContentProvider): Disposable; + + /** ++ * Register a [tree explorer node provider](#TreeExplorerNodeProvider).","tree explorer node provider -> TreeExplorerNodeProvider +",2016-10-24 15:23:09 +738,"@@ -384,6 +386,12 @@ class MouseDownOperation extends Disposable { + () => !this._viewHelper.isDirty() + ) + ); ++ this._mouseDragThenMoveEventHandler = this._register(","No need for a separate handler, I suggest to code the dnd case inside `onMouseDownThenMove`",2017-02-20 11:08:19 +26,"@@ -388,20 +388,21 @@ export interface ISuggestion { + label: string; + codeSnippet: string; + type: string; +- textEdit?: EditorCommon.ISingleEditOperation; + typeLabel?: string; + documentationLabel?: string; + filterText?: string; + sortText?: string; + noAutoAccept?: boolean; ++ overwriteBefore?: number; ++ overwriteAfter?: number; ++ ++ textEdit?: EditorCommon.ISingleEditOperation;","this isn't needed anymore, right? +",2015-12-11 10:25:03 +702,"@@ -389,6 +395,16 @@ export class DefaultController implements _.IController { + + return false; + } ++ ++ protected setOpenMode(openMode: WorkbenchOpenMode) { ++ if (this.options.openMode !== openMode) { ++ this.options.openMode = openMode; ++ } ++ } ++ ++ protected isInSingleClickOpenMode() {",Maybe better `openOnSingleClick`,2017-01-20 11:54:38 +883,"@@ -39,12 +42,42 @@ export class TerminalLinkHandler { + private _tooltipDisposables: IDisposable[] = []; + private _widgetManager: TerminalWidgetManager; + ++ // Changing any regex may effect this value, hence changes this as well if required. ++ private _winLineAndColumnMatchIndex = 12; ++ private _unixLineAndColumnMatchIndex = 15; ++ ++ private _lineAndColumnClauses = [",Any reason this isn't a constant up the top so it's shared between multiple instances of `TerminalLinkHandler`?,2017-04-17 17:37:21 +54,"@@ -391,11 +418,17 @@ export class Workbench implements IPartService { + this.sideBarHidden = true; // we hide sidebar in single-file-mode + } + +- let registry = (Registry.as(ViewletExtensions.Viewlets)); ++ let registry = (Registry.as(ViewletExtensions.Viewlets)); + if (!registry.getDefaultViewletId()) { + this.sideBarHidden = true; // can only hide sidebar if we dont have a default viewlet id","@isidorn for the sake of completness, the panel should also be hidden if there is no default panel +",2016-01-19 11:14:04 +826,"@@ -391,7 +391,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { + } else { + (this.terminalService.configHelper as TerminalConfigHelper).mergeDefaultShellPathAndArgs(shellLaunchConfig); + } +- let shellArgs = shellLaunchConfig.args.slice(0); ++ let shellArgs = shellLaunchConfig.args.slice(0);",@weinand FYI IShellLaunchConfig can now have args as a string to support @dbaeumer's use case of needed to use a pre-escaped set of arguments. I needed to make this change which I believe shouldn't cause any issues.,2017-03-14 18:22:28 +653,"@@ -392,3 +393,58 @@ export const isAbsoluteRegex = /^((\/|[a-zA-Z]:\\)[^\(\)<>\\'\""\[\]]+)/; + export function isAbsolute(path: string): boolean { + return isAbsoluteRegex.test(path); + } ++ ++/** ++ * Shortens the paths but keeps them easy to distinguish. ++ * Replaces not important parts with ellipsis. ++ * Every shorten path matches only one original path and vice versa. ++ */ ++export function shorten(paths: string[]): string[] { ++ var separator = isWindows ? '\\' : '/';",Suggest to use `paths.nativeSep` here (https://github.com/Microsoft/vscode/blob/master/src/vs/base/common/paths.ts#L20),2017-01-09 09:10:00 +655,"@@ -392,3 +393,58 @@ export const isAbsoluteRegex = /^((\/|[a-zA-Z]:\\)[^\(\)<>\\'\""\[\]]+)/; + export function isAbsolute(path: string): boolean { + return isAbsoluteRegex.test(path); + } ++ ++/** ++ * Shortens the paths but keeps them easy to distinguish. ++ * Replaces not important parts with ellipsis. ++ * Every shorten path matches only one original path and vice versa. ++ */ ++export function shorten(paths: string[]): string[] { ++ var separator = isWindows ? '\\' : '/'; ++ var ellipsis = '...';",How about using the actual unicode ellipsis character? I think that will save us some pixels (e.g. http://www.fileformat.info/info/unicode/char/2026/index.htm),2017-01-09 09:11:02 +105,"@@ -392,6 +392,9 @@ export class VSCodeMenu { + } + + private setOpenRecentMenu(openRecentMenu: Electron.Menu): void { ++ openRecentMenu.append(this.createMenuItem(nls.localize({ key: 'miReopenClosedFile', comment: ['&& denotes a mnemonic'] }, ""&&Reopen Closed File""), 'workbench.files.action.reopenClosedFile')); ++ openRecentMenu.append(__separator__());","@Tyriar careful, the menu might not have any entries (if there are not recent files) so you would have one separator too much in the end +",2016-04-15 06:13:35 +689,"@@ -392,9 +388,13 @@ export class MainThreadTextEditor { + return false; + } + +- insertSnippet(template: string, opts: IInsertSnippetOptions) { ++ insertSnippet(template: string, opts: IUndoStopOptions) {",@jrieken Should `console.warn('applyEdits on invisible editor');` be added to `insertSnippet`?,2017-01-18 18:22:48 +930,"@@ -394,6 +395,48 @@ export class ManageExtensionAction extends Action { + } + } + ++export class AddToWorkspaceRecommendationsAction extends Action implements IExtensionAction {","Since there is an action to add an extension to recommended list, there should also be a counter action to remove it from recommended list",2017-05-12 09:10:19 +927,"@@ -394,6 +395,48 @@ export class ManageExtensionAction extends Action { + } + } + ++export class AddToWorkspaceRecommendationsAction extends Action implements IExtensionAction { ++ ++ static ID = 'extensions.addToWorkspaceRecommendationsAction'; ++ static LABEL = localize('addToWorkspaceRecommendationsAction', ""Workspace""); ++ ++ private disposables: IDisposable[] = []; ++ ++ private _extension: IExtension; ++ get extension(): IExtension { return this._extension; } ++ set extension(extension: IExtension) { this._extension = extension; this.update(); } ++ ++ constructor(label: string, ++ @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, ++ @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, ++ @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, ++ @IInstantiationService private instantiationService: IInstantiationService",Please remove those services which are not used,2017-05-12 09:04:13 +929,"@@ -394,6 +395,48 @@ export class ManageExtensionAction extends Action { + } + } + ++export class AddToWorkspaceRecommendationsAction extends Action implements IExtensionAction { ++ ++ static ID = 'extensions.addToWorkspaceRecommendationsAction'; ++ static LABEL = localize('addToWorkspaceRecommendationsAction', ""Workspace""); ++ ++ private disposables: IDisposable[] = []; ++ ++ private _extension: IExtension; ++ get extension(): IExtension { return this._extension; } ++ set extension(extension: IExtension) { this._extension = extension; this.update(); } ++ ++ constructor(label: string, ++ @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, ++ @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, ++ @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, ++ @IInstantiationService private instantiationService: IInstantiationService ++ ) { ++ super(AddToWorkspaceRecommendationsAction.ID, label); ++ ++ this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update())); ++ this.update(); ++ } ++ ++ private update(): void { ++ this.enabled = !!this.extension;",Enablement should also depends on if it is already recommended or not and also if there is a workspace or not,2017-05-12 09:09:40 +922,"@@ -394,6 +395,48 @@ export class ManageExtensionAction extends Action { + } + } + ++export class AddToWorkspaceRecommendationsAction extends Action implements IExtensionAction { ++ ++ static ID = 'extensions.addToWorkspaceRecommendationsAction'; ++ static LABEL = localize('addToWorkspaceRecommendationsAction', ""Workspace""); ++ ++ private disposables: IDisposable[] = []; ++ ++ private _extension: IExtension; ++ get extension(): IExtension { return this._extension; } ++ set extension(extension: IExtension) { this._extension = extension; this.update(); } ++ ++ constructor(label: string, ++ @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, ++ @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, ++ @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, ++ @IInstantiationService private instantiationService: IInstantiationService ++ ) { ++ super(AddToWorkspaceRecommendationsAction.ID, label); ++ ++ this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update())); ++ this.update(); ++ } ++ ++ private update(): void { ++ this.enabled = !!this.extension; ++ } ++ ++ run(): TPromise { ++ const action = this.instantiationService.createInstance( ++ ConfigureWorkspaceRecommendedExtensionsAction, ++ ConfigureWorkspaceRecommendedExtensionsAction.ID, ++ ConfigureWorkspaceRecommendedExtensionsAction.LABEL","- Check for the case when there is no workspace. +- Also why do we need to show the extensions file if we can just add the recommendation silently in the background.",2017-05-12 08:45:09 +923,"@@ -394,6 +395,48 @@ export class ManageExtensionAction extends Action { + } + } + ++export class AddToWorkspaceRecommendationsAction extends Action implements IExtensionAction { ++ ++ static ID = 'extensions.addToWorkspaceRecommendationsAction'; ++ static LABEL = localize('addToWorkspaceRecommendationsAction', ""Workspace""); ++ ++ private disposables: IDisposable[] = []; ++ ++ private _extension: IExtension; ++ get extension(): IExtension { return this._extension; } ++ set extension(extension: IExtension) { this._extension = extension; this.update(); } ++ ++ constructor(label: string, ++ @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, ++ @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, ++ @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, ++ @IInstantiationService private instantiationService: IInstantiationService ++ ) { ++ super(AddToWorkspaceRecommendationsAction.ID, label); ++ ++ this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update())); ++ this.update(); ++ } ++ ++ private update(): void { ++ this.enabled = !!this.extension; ++ } ++ ++ run(): TPromise { ++ const action = this.instantiationService.createInstance( ++ ConfigureWorkspaceRecommendedExtensionsAction, ++ ConfigureWorkspaceRecommendedExtensionsAction.ID, ++ ConfigureWorkspaceRecommendedExtensionsAction.LABEL ++ ); ++ return action.run() ++ .then(() => this.extensionsWorkbenchService.addToWorkspaceRecommendations(this.extension));",Why not call the ExtensionTip service directly to add a recommendation?,2017-05-12 08:46:46 +790,"@@ -394,7 +394,10 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient + if (!fs.existsSync(modulePath)) { + window.showWarningMessage(localize('noServerFound', 'The path {0} doesn\'t point to a valid tsserver install. Falling back to bundled TypeScript version.', path.dirname(modulePath))); + modulePath = this.bundledTypeScriptPath; +- // TODO check again? ++ if (!fs.existsSync(modulePath)) { ++ window.showErrorMessage(localize('noBundledServerFound', 'Could not find VSCode\'s tsserver install. Please try reinstalling VSCode'));","This error message is only visible in the rare case that the installation was corrupted by a third party program. I think we should be explicit in calling it out: ""VSCode's tsserver was deleted by a another application such as a misbehaving virus detection tool. Please reinstall VS Code."" Otherwise, if I'd see the message you propose right now, I'd think VS Code did something wrong.",2017-03-02 16:25:06 +857,"@@ -4,7 +4,7 @@ + *--------------------------------------------------------------------------------------------*/ + 'use strict'; + +-import { Emitter } from 'vs/base/common/event'; ++import { Emitter, createEmptyEvent } from 'vs/base/common/event';",Event.none?,2017-03-24 09:49:21 +235,"@@ -4,8 +4,9 @@ + *--------------------------------------------------------------------------------------------*/ + 'use strict'; + +-import {onUnexpectedError} from 'vs/base/common/errors'; ++import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; + import * as strings from 'vs/base/common/strings'; ++import types = require('vs/base/common/types');","no more old school require pls +",2016-07-15 11:23:31 +231,"@@ -4,9 +4,11 @@ + *--------------------------------------------------------------------------------------------*/ + 'use strict'; + ++import nls = require('vs/nls');","no more old school require please +",2016-07-15 11:19:06 +230,"@@ -4,9 +4,11 @@ + *--------------------------------------------------------------------------------------------*/ + 'use strict'; + ++import nls = require('vs/nls'); + import {IAction} from 'vs/base/common/actions'; + import {IEventEmitter, BulkListenerCallback} from 'vs/base/common/eventEmitter'; + import {MarkedString} from 'vs/base/common/htmlContent'; ++import types = require('vs/base/common/types');","no more old school require please +",2016-07-15 11:18:59 +149,"@@ -40,10 +40,10 @@ exports.loaderConfig = function (emptyPaths) { + paths: { + 'vs/extensions': 'extensions' + } +- } ++ }, ++ nodeModules: emptyPaths||[]","Is this change related to 3077? +",2016-05-20 08:17:59 +966,"@@ -40,6 +40,10 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenViewPickerAct + primary: KeyMod.CtrlCmd | KeyCode.KEY_Q, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_Q }, linux: { primary: null } + }), 'Quick Open View'); + ++registry.registerWorkbenchAction(new SyncActionDescriptor(ShowTasksAction, ShowTasksAction.ID, ShowTasksAction.LABEL, {",`cmd+shift+t` is taken by 'Reopen closed editor',2017-06-12 21:25:25 +73,"@@ -40,8 +40,8 @@ export class Source { + // first try to find the raw source amongst the stack frames - since that represenation has more data (source reference),","Looks good. +",2016-03-16 10:25:09 +583,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' ||","trimmedLinesContent.length could be 0 here, leading to a call of `trimmedLinesContent.charAt(-1)`. + +You could use if (insertSpace && ....)",2016-12-05 17:09:59 +584,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' || ++ trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t') { ++ insertSpace = false; ++ trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' '); ++ } ++ ++ let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1); ++ ++ if (lineTextWithoutIndent.charAt(0) === ')') {","Why are we looking for `)` in the line text here ? i.e. this looks weird to me, why not for `]`. I suggest to remove this unless it is part of some weird join lines spec.",2016-12-05 17:13:08 +585,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' || ++ trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t') { ++ insertSpace = false; ++ trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' '); ++ } ++ ++ let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1); ++ ++ if (lineTextWithoutIndent.charAt(0) === ')') { ++ insertSpace = false; ++ } ++ ++ trimmedLinesContent += (insertSpace ? ' ' : '') + lineTextWithoutIndent; ++ ++ if (insertSpace) { ++ columnDeltaOffset = lineTextWithoutIndent.length + 1; ++ } else { ++ columnDeltaOffset = lineTextWithoutIndent.length; ++ } ++ } else { ++ columnDeltaOffset = 0; ++ } ++ } ++ ++ let deleteSelection = new Range( ++ startLineNumber, ++ startColumn, ++ endLineNumber, ++ endColumn ++ ); ++ ++ if (!deleteSelection.isEmpty()) { ++ if (selection.isEmpty()) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandWithOffsetCursorState(deleteSelection, trimmedLinesContent, 0, -columnDeltaOffset) ++ ); ++ } else { ++ if (selection.startLineNumber === selection.endLineNumber) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandThatPreservesSelection(deleteSelection, trimmedLinesContent, selection) ++ ); ++ } else { ++ editor.executeCommand(this.id, new ReplaceCommand(deleteSelection, trimmedLinesContent)); ++ editor.setSelection(new Selection(selection.startLineNumber, selection.startColumn, ++ selection.startLineNumber, trimmedLinesContent.length - selectionEndPositionOffset)); ++ } ++ } ++ } ++ } ++} ++ ++@editorAction ++export class TransposeAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transpose', ++ label: nls.localize('editor.transpose', ""Transpose characters around the cursor""), ++ alias: 'Transpose characters around the cursor', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ if (cursor.column > model.getLineContent(cursor.lineNumber).length) { ++ return; ++ } ++ ++ let deleteSelection = new Range(cursor.lineNumber, Math.max(1, cursor.column - 1), cursor.lineNumber, cursor.column + 1); ++ let chars = model.getValueInRange(deleteSelection).split('').reverse().join(''); ++ commands.push(new ReplaceCommandThatPreservesSelection(deleteSelection, chars, ++ new Selection(cursor.lineNumber, cursor.column + 1, cursor.lineNumber, cursor.column + 1))); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++class PasteAndFormatAction extends EditorAction {",":-1: IMHO on this action. + +I would prefer to have an `editor.formatOnPaste` which in my opinion would align more with our current approach to automatic formatting (same as `formatOnType` and `formatOnSave`). @jrieken what do you think? + +This one also assumes it knows how paste is implemented in the cursor, but in case of multicursor paste touches multiple ranges, not just one. i.e. `pastedContentRange` is incorrect in case of multicursor paste. + +I suggest to wait with this action and consider implementing it in the format contribution, we are shipping since a long time without it, and there's no reason to rush it in.",2016-12-05 17:23:15 +586,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' || ++ trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t') { ++ insertSpace = false; ++ trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' '); ++ } ++ ++ let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1); ++ ++ if (lineTextWithoutIndent.charAt(0) === ')') { ++ insertSpace = false; ++ } ++ ++ trimmedLinesContent += (insertSpace ? ' ' : '') + lineTextWithoutIndent; ++ ++ if (insertSpace) { ++ columnDeltaOffset = lineTextWithoutIndent.length + 1; ++ } else { ++ columnDeltaOffset = lineTextWithoutIndent.length; ++ } ++ } else { ++ columnDeltaOffset = 0; ++ } ++ } ++ ++ let deleteSelection = new Range( ++ startLineNumber, ++ startColumn, ++ endLineNumber, ++ endColumn ++ ); ++ ++ if (!deleteSelection.isEmpty()) { ++ if (selection.isEmpty()) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandWithOffsetCursorState(deleteSelection, trimmedLinesContent, 0, -columnDeltaOffset) ++ ); ++ } else { ++ if (selection.startLineNumber === selection.endLineNumber) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandThatPreservesSelection(deleteSelection, trimmedLinesContent, selection) ++ ); ++ } else { ++ editor.executeCommand(this.id, new ReplaceCommand(deleteSelection, trimmedLinesContent)); ++ editor.setSelection(new Selection(selection.startLineNumber, selection.startColumn, ++ selection.startLineNumber, trimmedLinesContent.length - selectionEndPositionOffset)); ++ } ++ } ++ } ++ } ++} ++ ++@editorAction ++export class TransposeAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transpose', ++ label: nls.localize('editor.transpose', ""Transpose characters around the cursor""), ++ alias: 'Transpose characters around the cursor', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ if (cursor.column > model.getLineContent(cursor.lineNumber).length) { ++ return; ++ } ++ ++ let deleteSelection = new Range(cursor.lineNumber, Math.max(1, cursor.column - 1), cursor.lineNumber, cursor.column + 1); ++ let chars = model.getValueInRange(deleteSelection).split('').reverse().join(''); ++ commands.push(new ReplaceCommandThatPreservesSelection(deleteSelection, chars, ++ new Selection(cursor.lineNumber, cursor.column + 1, cursor.lineNumber, cursor.column + 1))); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++class PasteAndFormatAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.pasteAndFormat', ++ label: nls.localize('editor.pasteAndFormat', ""Paste and format""), ++ alias: 'Paste and format', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise { ++ const originalCursorPosition = editor.getSelection().getStartPosition(); ++ ++ // 1. paste ++ editor.focus(); ++ document.execCommand('paste'); ++ ++ const currentCursorPosition = editor.getSelection().getStartPosition(); ++ const pastedContentRange = new Selection(currentCursorPosition.lineNumber, currentCursorPosition.column, originalCursorPosition.lineNumber, originalCursorPosition.column); ++ ++ // 2. format ++ const model = editor.getModel(); ++ const { tabSize, insertSpaces } = model.getOptions(); ++ const workerService = accessor.get(IEditorWorkerService); ++ const formattingPromise = getDocumentRangeFormattingEdits(model, pastedContentRange, { tabSize, insertSpaces }); ++ ++ if (!formattingPromise) { ++ return TPromise.as(void 0); ++ } ++ ++ const state = editor.captureState(CodeEditorStateFlag.Value, CodeEditorStateFlag.Position); ++ ++ return formattingPromise.then(edits => workerService.computeMoreMinimalEdits(editor.getModel().uri, edits, editor.getSelections())).then(edits => { ++ if (!state.validate(editor) || isFalsyOrEmpty(edits)) { ++ return; ++ } ++ ++ const command = new EditOperationsCommand(edits, editor.getSelection()); ++ editor.executeCommand(this.id, command); ++ editor.focus(); ++ ++ // 3. update cursor positions ++ let selection = editor.getSelection(); ++ selection = new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn); ++ editor.setSelection(selection); ++ }); ++ } ++} ++ ++@editorAction ++export class UpperCaseAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transformToUppercase', ++ label: nls.localize('editor.transformToUppercase', ""Transform to Uppercase""), ++ alias: 'Transform to Uppercase', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ let word = model.getWordAtPosition(cursor);",`word` can be null here,2016-12-05 17:24:34 +587,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' || ++ trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t') { ++ insertSpace = false; ++ trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' '); ++ } ++ ++ let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1); ++ ++ if (lineTextWithoutIndent.charAt(0) === ')') { ++ insertSpace = false; ++ } ++ ++ trimmedLinesContent += (insertSpace ? ' ' : '') + lineTextWithoutIndent; ++ ++ if (insertSpace) { ++ columnDeltaOffset = lineTextWithoutIndent.length + 1; ++ } else { ++ columnDeltaOffset = lineTextWithoutIndent.length; ++ } ++ } else { ++ columnDeltaOffset = 0; ++ } ++ } ++ ++ let deleteSelection = new Range( ++ startLineNumber, ++ startColumn, ++ endLineNumber, ++ endColumn ++ ); ++ ++ if (!deleteSelection.isEmpty()) { ++ if (selection.isEmpty()) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandWithOffsetCursorState(deleteSelection, trimmedLinesContent, 0, -columnDeltaOffset) ++ ); ++ } else { ++ if (selection.startLineNumber === selection.endLineNumber) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandThatPreservesSelection(deleteSelection, trimmedLinesContent, selection) ++ ); ++ } else { ++ editor.executeCommand(this.id, new ReplaceCommand(deleteSelection, trimmedLinesContent)); ++ editor.setSelection(new Selection(selection.startLineNumber, selection.startColumn, ++ selection.startLineNumber, trimmedLinesContent.length - selectionEndPositionOffset)); ++ } ++ } ++ } ++ } ++} ++ ++@editorAction ++export class TransposeAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transpose', ++ label: nls.localize('editor.transpose', ""Transpose characters around the cursor""), ++ alias: 'Transpose characters around the cursor', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ if (cursor.column > model.getLineContent(cursor.lineNumber).length) { ++ return; ++ } ++ ++ let deleteSelection = new Range(cursor.lineNumber, Math.max(1, cursor.column - 1), cursor.lineNumber, cursor.column + 1); ++ let chars = model.getValueInRange(deleteSelection).split('').reverse().join(''); ++ commands.push(new ReplaceCommandThatPreservesSelection(deleteSelection, chars, ++ new Selection(cursor.lineNumber, cursor.column + 1, cursor.lineNumber, cursor.column + 1))); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++class PasteAndFormatAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.pasteAndFormat', ++ label: nls.localize('editor.pasteAndFormat', ""Paste and format""), ++ alias: 'Paste and format', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise { ++ const originalCursorPosition = editor.getSelection().getStartPosition(); ++ ++ // 1. paste ++ editor.focus(); ++ document.execCommand('paste'); ++ ++ const currentCursorPosition = editor.getSelection().getStartPosition(); ++ const pastedContentRange = new Selection(currentCursorPosition.lineNumber, currentCursorPosition.column, originalCursorPosition.lineNumber, originalCursorPosition.column); ++ ++ // 2. format ++ const model = editor.getModel(); ++ const { tabSize, insertSpaces } = model.getOptions(); ++ const workerService = accessor.get(IEditorWorkerService); ++ const formattingPromise = getDocumentRangeFormattingEdits(model, pastedContentRange, { tabSize, insertSpaces }); ++ ++ if (!formattingPromise) { ++ return TPromise.as(void 0); ++ } ++ ++ const state = editor.captureState(CodeEditorStateFlag.Value, CodeEditorStateFlag.Position); ++ ++ return formattingPromise.then(edits => workerService.computeMoreMinimalEdits(editor.getModel().uri, edits, editor.getSelections())).then(edits => { ++ if (!state.validate(editor) || isFalsyOrEmpty(edits)) { ++ return; ++ } ++ ++ const command = new EditOperationsCommand(edits, editor.getSelection()); ++ editor.executeCommand(this.id, command); ++ editor.focus(); ++ ++ // 3. update cursor positions ++ let selection = editor.getSelection(); ++ selection = new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn); ++ editor.setSelection(selection); ++ }); ++ } ++} ++ ++@editorAction ++export class UpperCaseAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transformToUppercase', ++ label: nls.localize('editor.transformToUppercase', ""Transform to Uppercase""), ++ alias: 'Transform to Uppercase', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ let word = model.getWordAtPosition(cursor); ++ let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); ++ ++ if (wordRange !== undefined) {",???,2016-12-05 17:24:42 +590,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' || ++ trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t') { ++ insertSpace = false; ++ trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' '); ++ } ++ ++ let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1); ++ ++ if (lineTextWithoutIndent.charAt(0) === ')') { ++ insertSpace = false; ++ } ++ ++ trimmedLinesContent += (insertSpace ? ' ' : '') + lineTextWithoutIndent; ++ ++ if (insertSpace) { ++ columnDeltaOffset = lineTextWithoutIndent.length + 1; ++ } else { ++ columnDeltaOffset = lineTextWithoutIndent.length; ++ } ++ } else { ++ columnDeltaOffset = 0; ++ } ++ } ++ ++ let deleteSelection = new Range( ++ startLineNumber, ++ startColumn, ++ endLineNumber, ++ endColumn ++ ); ++ ++ if (!deleteSelection.isEmpty()) { ++ if (selection.isEmpty()) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandWithOffsetCursorState(deleteSelection, trimmedLinesContent, 0, -columnDeltaOffset) ++ ); ++ } else { ++ if (selection.startLineNumber === selection.endLineNumber) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandThatPreservesSelection(deleteSelection, trimmedLinesContent, selection) ++ ); ++ } else { ++ editor.executeCommand(this.id, new ReplaceCommand(deleteSelection, trimmedLinesContent)); ++ editor.setSelection(new Selection(selection.startLineNumber, selection.startColumn, ++ selection.startLineNumber, trimmedLinesContent.length - selectionEndPositionOffset)); ++ } ++ } ++ } ++ } ++} ++ ++@editorAction ++export class TransposeAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transpose', ++ label: nls.localize('editor.transpose', ""Transpose characters around the cursor""), ++ alias: 'Transpose characters around the cursor', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ if (cursor.column > model.getLineContent(cursor.lineNumber).length) { ++ return; ++ } ++ ++ let deleteSelection = new Range(cursor.lineNumber, Math.max(1, cursor.column - 1), cursor.lineNumber, cursor.column + 1); ++ let chars = model.getValueInRange(deleteSelection).split('').reverse().join(''); ++ commands.push(new ReplaceCommandThatPreservesSelection(deleteSelection, chars, ++ new Selection(cursor.lineNumber, cursor.column + 1, cursor.lineNumber, cursor.column + 1))); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++class PasteAndFormatAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.pasteAndFormat', ++ label: nls.localize('editor.pasteAndFormat', ""Paste and format""), ++ alias: 'Paste and format', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise { ++ const originalCursorPosition = editor.getSelection().getStartPosition(); ++ ++ // 1. paste ++ editor.focus(); ++ document.execCommand('paste'); ++ ++ const currentCursorPosition = editor.getSelection().getStartPosition(); ++ const pastedContentRange = new Selection(currentCursorPosition.lineNumber, currentCursorPosition.column, originalCursorPosition.lineNumber, originalCursorPosition.column); ++ ++ // 2. format ++ const model = editor.getModel(); ++ const { tabSize, insertSpaces } = model.getOptions(); ++ const workerService = accessor.get(IEditorWorkerService); ++ const formattingPromise = getDocumentRangeFormattingEdits(model, pastedContentRange, { tabSize, insertSpaces }); ++ ++ if (!formattingPromise) { ++ return TPromise.as(void 0); ++ } ++ ++ const state = editor.captureState(CodeEditorStateFlag.Value, CodeEditorStateFlag.Position); ++ ++ return formattingPromise.then(edits => workerService.computeMoreMinimalEdits(editor.getModel().uri, edits, editor.getSelections())).then(edits => { ++ if (!state.validate(editor) || isFalsyOrEmpty(edits)) { ++ return; ++ } ++ ++ const command = new EditOperationsCommand(edits, editor.getSelection()); ++ editor.executeCommand(this.id, command); ++ editor.focus(); ++ ++ // 3. update cursor positions ++ let selection = editor.getSelection(); ++ selection = new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn); ++ editor.setSelection(selection); ++ }); ++ } ++} ++ ++@editorAction ++export class UpperCaseAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transformToUppercase', ++ label: nls.localize('editor.transformToUppercase', ""Transform to Uppercase""), ++ alias: 'Transform to Uppercase', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ let word = model.getWordAtPosition(cursor); ++ let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); ++ ++ if (wordRange !== undefined) { ++ let text = model.getValueInRange(wordRange); ++ commands.push(new ReplaceCommandThatPreservesSelection(wordRange, text.toLocaleUpperCase(), ++ new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column))); ++ } ++ } else { ++ let text = model.getValueInRange(selection); ++ commands.push(new ReplaceCommandThatPreservesSelection(selection, text.toLocaleUpperCase(), selection)); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++export class LowerCaseAction extends EditorAction {",I suggest to create an abstract `CaseAction` that has an abstract method `_modifyText` or whatever that can be overwritten to use `toLocaleUpperCase` and `toLocalLowerCase` to avoid code duplication.,2016-12-05 17:31:57 +588,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' || ++ trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t') { ++ insertSpace = false; ++ trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' '); ++ } ++ ++ let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1); ++ ++ if (lineTextWithoutIndent.charAt(0) === ')') { ++ insertSpace = false; ++ } ++ ++ trimmedLinesContent += (insertSpace ? ' ' : '') + lineTextWithoutIndent; ++ ++ if (insertSpace) { ++ columnDeltaOffset = lineTextWithoutIndent.length + 1; ++ } else { ++ columnDeltaOffset = lineTextWithoutIndent.length; ++ } ++ } else { ++ columnDeltaOffset = 0; ++ } ++ } ++ ++ let deleteSelection = new Range( ++ startLineNumber, ++ startColumn, ++ endLineNumber, ++ endColumn ++ ); ++ ++ if (!deleteSelection.isEmpty()) { ++ if (selection.isEmpty()) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandWithOffsetCursorState(deleteSelection, trimmedLinesContent, 0, -columnDeltaOffset) ++ ); ++ } else { ++ if (selection.startLineNumber === selection.endLineNumber) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandThatPreservesSelection(deleteSelection, trimmedLinesContent, selection) ++ ); ++ } else { ++ editor.executeCommand(this.id, new ReplaceCommand(deleteSelection, trimmedLinesContent)); ++ editor.setSelection(new Selection(selection.startLineNumber, selection.startColumn, ++ selection.startLineNumber, trimmedLinesContent.length - selectionEndPositionOffset)); ++ } ++ } ++ } ++ } ++} ++ ++@editorAction ++export class TransposeAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transpose', ++ label: nls.localize('editor.transpose', ""Transpose characters around the cursor""), ++ alias: 'Transpose characters around the cursor', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ if (cursor.column > model.getLineContent(cursor.lineNumber).length) { ++ return; ++ } ++ ++ let deleteSelection = new Range(cursor.lineNumber, Math.max(1, cursor.column - 1), cursor.lineNumber, cursor.column + 1); ++ let chars = model.getValueInRange(deleteSelection).split('').reverse().join(''); ++ commands.push(new ReplaceCommandThatPreservesSelection(deleteSelection, chars, ++ new Selection(cursor.lineNumber, cursor.column + 1, cursor.lineNumber, cursor.column + 1))); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++class PasteAndFormatAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.pasteAndFormat', ++ label: nls.localize('editor.pasteAndFormat', ""Paste and format""), ++ alias: 'Paste and format', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise { ++ const originalCursorPosition = editor.getSelection().getStartPosition(); ++ ++ // 1. paste ++ editor.focus(); ++ document.execCommand('paste'); ++ ++ const currentCursorPosition = editor.getSelection().getStartPosition(); ++ const pastedContentRange = new Selection(currentCursorPosition.lineNumber, currentCursorPosition.column, originalCursorPosition.lineNumber, originalCursorPosition.column); ++ ++ // 2. format ++ const model = editor.getModel(); ++ const { tabSize, insertSpaces } = model.getOptions(); ++ const workerService = accessor.get(IEditorWorkerService); ++ const formattingPromise = getDocumentRangeFormattingEdits(model, pastedContentRange, { tabSize, insertSpaces }); ++ ++ if (!formattingPromise) { ++ return TPromise.as(void 0); ++ } ++ ++ const state = editor.captureState(CodeEditorStateFlag.Value, CodeEditorStateFlag.Position); ++ ++ return formattingPromise.then(edits => workerService.computeMoreMinimalEdits(editor.getModel().uri, edits, editor.getSelections())).then(edits => { ++ if (!state.validate(editor) || isFalsyOrEmpty(edits)) { ++ return; ++ } ++ ++ const command = new EditOperationsCommand(edits, editor.getSelection()); ++ editor.executeCommand(this.id, command); ++ editor.focus(); ++ ++ // 3. update cursor positions ++ let selection = editor.getSelection(); ++ selection = new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn); ++ editor.setSelection(selection); ++ }); ++ } ++} ++ ++@editorAction ++export class UpperCaseAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transformToUppercase', ++ label: nls.localize('editor.transformToUppercase', ""Transform to Uppercase""), ++ alias: 'Transform to Uppercase', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ let word = model.getWordAtPosition(cursor); ++ let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); ++ ++ if (wordRange !== undefined) { ++ let text = model.getValueInRange(wordRange); ++ commands.push(new ReplaceCommandThatPreservesSelection(wordRange, text.toLocaleUpperCase(), ++ new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column))); ++ } ++ } else { ++ let text = model.getValueInRange(selection); ++ commands.push(new ReplaceCommandThatPreservesSelection(selection, text.toLocaleUpperCase(), selection)); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++export class LowerCaseAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transformToLowercase', ++ label: nls.localize('editor.transformToLowercase', ""Transform to Lowercase""), ++ alias: 'Transform to Lowercase', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ let word = model.getWordAtPosition(cursor);",`word` can be null here. think of empty lines.,2016-12-05 17:25:00 +589,"@@ -401,3 +407,267 @@ export class DeleteAllLeftAction extends EditorAction { + editor.executeEdits(this.id, edits); + } + } ++ ++@editorAction ++export class JoinLinesAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.joinLines', ++ label: nls.localize('lines.joinLines', ""Join Lines""), ++ alias: 'Join Lines', ++ precondition: EditorContextKeys.Writable, ++ kbOpts: { ++ kbExpr: EditorContextKeys.TextFocus, ++ primary: KeyMod.WinCtrl | KeyCode.KEY_J ++ } ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selection = editor.getSelection(); ++ let model = editor.getModel(); ++ let startLineNumber = selection.startLineNumber; ++ let startColumn = 1; ++ let endLineNumber: number, ++ endColumn: number, ++ columnDeltaOffset: number; ++ ++ let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn; ++ ++ if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) { ++ let position = selection.getStartPosition(); ++ if (position.lineNumber < model.getLineCount()) { ++ endLineNumber = startLineNumber + 1; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } else { ++ endLineNumber = position.lineNumber; ++ endColumn = model.getLineMaxColumn(position.lineNumber); ++ } ++ } else { ++ endLineNumber = selection.endLineNumber; ++ endColumn = model.getLineMaxColumn(endLineNumber); ++ } ++ ++ let trimmedLinesContent = model.getLineContent(startLineNumber); ++ ++ for (let i = startLineNumber + 1; i <= endLineNumber; i++) { ++ let lineText = model.getLineContent(i); ++ let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i); ++ ++ if (firstNonWhitespaceIdx >= 1) { ++ let insertSpace = true; ++ if (trimmedLinesContent === '') { ++ insertSpace = false; ++ } ++ ++ if (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' || ++ trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t') { ++ insertSpace = false; ++ trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' '); ++ } ++ ++ let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1); ++ ++ if (lineTextWithoutIndent.charAt(0) === ')') { ++ insertSpace = false; ++ } ++ ++ trimmedLinesContent += (insertSpace ? ' ' : '') + lineTextWithoutIndent; ++ ++ if (insertSpace) { ++ columnDeltaOffset = lineTextWithoutIndent.length + 1; ++ } else { ++ columnDeltaOffset = lineTextWithoutIndent.length; ++ } ++ } else { ++ columnDeltaOffset = 0; ++ } ++ } ++ ++ let deleteSelection = new Range( ++ startLineNumber, ++ startColumn, ++ endLineNumber, ++ endColumn ++ ); ++ ++ if (!deleteSelection.isEmpty()) { ++ if (selection.isEmpty()) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandWithOffsetCursorState(deleteSelection, trimmedLinesContent, 0, -columnDeltaOffset) ++ ); ++ } else { ++ if (selection.startLineNumber === selection.endLineNumber) { ++ editor.executeCommand(this.id, ++ new ReplaceCommandThatPreservesSelection(deleteSelection, trimmedLinesContent, selection) ++ ); ++ } else { ++ editor.executeCommand(this.id, new ReplaceCommand(deleteSelection, trimmedLinesContent)); ++ editor.setSelection(new Selection(selection.startLineNumber, selection.startColumn, ++ selection.startLineNumber, trimmedLinesContent.length - selectionEndPositionOffset)); ++ } ++ } ++ } ++ } ++} ++ ++@editorAction ++export class TransposeAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transpose', ++ label: nls.localize('editor.transpose', ""Transpose characters around the cursor""), ++ alias: 'Transpose characters around the cursor', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ if (cursor.column > model.getLineContent(cursor.lineNumber).length) { ++ return; ++ } ++ ++ let deleteSelection = new Range(cursor.lineNumber, Math.max(1, cursor.column - 1), cursor.lineNumber, cursor.column + 1); ++ let chars = model.getValueInRange(deleteSelection).split('').reverse().join(''); ++ commands.push(new ReplaceCommandThatPreservesSelection(deleteSelection, chars, ++ new Selection(cursor.lineNumber, cursor.column + 1, cursor.lineNumber, cursor.column + 1))); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++class PasteAndFormatAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.pasteAndFormat', ++ label: nls.localize('editor.pasteAndFormat', ""Paste and format""), ++ alias: 'Paste and format', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise { ++ const originalCursorPosition = editor.getSelection().getStartPosition(); ++ ++ // 1. paste ++ editor.focus(); ++ document.execCommand('paste'); ++ ++ const currentCursorPosition = editor.getSelection().getStartPosition(); ++ const pastedContentRange = new Selection(currentCursorPosition.lineNumber, currentCursorPosition.column, originalCursorPosition.lineNumber, originalCursorPosition.column); ++ ++ // 2. format ++ const model = editor.getModel(); ++ const { tabSize, insertSpaces } = model.getOptions(); ++ const workerService = accessor.get(IEditorWorkerService); ++ const formattingPromise = getDocumentRangeFormattingEdits(model, pastedContentRange, { tabSize, insertSpaces }); ++ ++ if (!formattingPromise) { ++ return TPromise.as(void 0); ++ } ++ ++ const state = editor.captureState(CodeEditorStateFlag.Value, CodeEditorStateFlag.Position); ++ ++ return formattingPromise.then(edits => workerService.computeMoreMinimalEdits(editor.getModel().uri, edits, editor.getSelections())).then(edits => { ++ if (!state.validate(editor) || isFalsyOrEmpty(edits)) { ++ return; ++ } ++ ++ const command = new EditOperationsCommand(edits, editor.getSelection()); ++ editor.executeCommand(this.id, command); ++ editor.focus(); ++ ++ // 3. update cursor positions ++ let selection = editor.getSelection(); ++ selection = new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn); ++ editor.setSelection(selection); ++ }); ++ } ++} ++ ++@editorAction ++export class UpperCaseAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transformToUppercase', ++ label: nls.localize('editor.transformToUppercase', ""Transform to Uppercase""), ++ alias: 'Transform to Uppercase', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ let word = model.getWordAtPosition(cursor); ++ let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); ++ ++ if (wordRange !== undefined) { ++ let text = model.getValueInRange(wordRange); ++ commands.push(new ReplaceCommandThatPreservesSelection(wordRange, text.toLocaleUpperCase(), ++ new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column))); ++ } ++ } else { ++ let text = model.getValueInRange(selection); ++ commands.push(new ReplaceCommandThatPreservesSelection(selection, text.toLocaleUpperCase(), selection)); ++ } ++ } ++ ++ editor.executeCommands(this.id, commands); ++ } ++} ++ ++@editorAction ++export class LowerCaseAction extends EditorAction { ++ constructor() { ++ super({ ++ id: 'editor.action.transformToLowercase', ++ label: nls.localize('editor.transformToLowercase', ""Transform to Lowercase""), ++ alias: 'Transform to Lowercase', ++ precondition: EditorContextKeys.Writable ++ }); ++ } ++ ++ public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { ++ let selections = editor.getSelections(); ++ let model = editor.getModel(); ++ let commands: ICommand[] = []; ++ ++ for (let i = 0, len = selections.length; i < len; i++) { ++ let selection = selections[i]; ++ if (selection.isEmpty()) { ++ let cursor = selection.getStartPosition(); ++ let word = model.getWordAtPosition(cursor); ++ let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); ++ ++ if (wordRange !== undefined) {",same ??,2016-12-05 17:25:10 +302,"@@ -404,7 +404,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService + } + + // Focus (unless prevented) +- const focus = !options || !options.preserveFocus; ++ const focus = !options || options.preserveFocus;","This cannot be changed... +",2016-10-05 08:11:45 +721,"@@ -406,15 +409,15 @@ export class WindowsManager implements IWindowsMainService { + } + + // Open Files in last instance if any and flag tells us so",The comment should probably be updated,2017-02-07 06:25:31 +739,"@@ -407,12 +415,30 @@ class MouseDownOperation extends Disposable { + this._dispatchMouse(position, true); + } + ++ private _onMouseDragThenMove(e: EditorMouseEvent): void {","Merge into `_onMouseDownThenMove` and use `mouseState.lastMouseDownEvent` (which should be renamed to something better, see other comment) to differentiate the two cases",2017-02-20 11:09:03 +740,"@@ -407,12 +415,30 @@ class MouseDownOperation extends Disposable { + this._dispatchMouse(position, true); + } + ++ private _onMouseDragThenMove(e: EditorMouseEvent): void { ++ this._lastMouseEvent = e; ++ this._mouseState.setModifiers(e); ++ this._mouseState.setMouseDownEvent('drag');",`this._mouseState.setMouseDownEvent('drag');` should move to the `start` method when the operation starts. The `lastMouseDownEvent` should be set only once when the operation starts inside `start`.,2017-02-20 11:10:21 +805,"@@ -4085,7 +4085,7 @@ declare module 'vscode' { + * @param options Options to control how the document will be created. + * @return A promise that resolves to a [document](#TextDocument). + */ +- export function openTextDocument(options?: { language: string; }): Thenable; ++ export function openTextDocument(options?: { language?: string; contents?: string; }): Thenable;","missing jsdoc-comment, also use `content` to align with `TextDocumentContentProvider`",2017-03-07 08:20:45 +859,"@@ -409,6 +409,10 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ + onWillSaveTextDocument: (listener, thisArgs?, disposables?) => { + return extHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables); + }, ++ onDidChangeDiffInformation: (listener, thisArgs?, disposables?) => { ++ // TODO@joao ++ return createEmptyEvent()(listener, thisArgs, disposables);",We could the be smart about this and *only* send these event from the main side when we have listeners on the ext host side,2017-03-24 09:50:58 +918,"@@ -41,13 +41,12 @@ + } + }, + ""scripts"": { +- ""compile"": ""node ./node_modules/vscode/bin/compile -watch -p ./"", +- ""vscode:prepublish"": ""node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-api-tests ./tsconfig.json"" ++ ""compile"": ""gulp compile-extension:vscode-api-tests"", ++ ""watch"": ""gulp watch-extension:vscode-api-tests""",The extension shouldn't have an implicit dependency on the *parent* project/package.json. Now it misses the dependency to `gulp` and `typescript`. I'd reckon to simply update the `typescript` dependency here,2017-05-09 07:34:17 +375,"@@ -41,13 +43,16 @@ export class UntitledEditorModel extends StringEditorModel implements IEncodingS + @IModeService modeService: IModeService, + @IModelService modelService: IModelService, + @IFileService private fileService: IFileService, +- @IConfigurationService private configurationService: IConfigurationService ++ @IConfigurationService private configurationService: IConfigurationService, ++ @IBackupService private backupService: IBackupService,","Unused service? +",2016-10-21 14:03:37 +373,"@@ -41,19 +42,26 @@ export class UntitledEditorInput extends AbstractUntitledEditorInput { + resource: URI, + hasAssociatedFilePath: boolean, + modeId: string, ++ restoreResource: URI, + @IInstantiationService private instantiationService: IInstantiationService, + @IWorkspaceContextService private contextService: IWorkspaceContextService, + @IModeService private modeService: IModeService, + @ITextFileService private textFileService: ITextFileService + ) { + super(); + this.resource = resource; ++ this.restoreResource = restoreResource;","As mentioned before I think we can get rid of the restoreResource also for untitled. The untitled model should go to the backup service and ask for available backups with the resource URI, similar to how text files now ask. +",2016-10-21 14:01:46 +175,"@@ -41,6 +41,14 @@ configurationRegistry.registerConfiguration({ + 'terminal.integrated.fontFamily': { + 'description': nls.localize('terminal.integrated.fontFamily', ""The font family used by the terminal (CSS font-family format), this defaults to editor.fontFamily's value.""), + 'type': 'string' ++ }, ++ 'terminal.integrated.fontSize': {","Font size should have a default here, otherwise auto-complete does this. + +![image](https://cloud.githubusercontent.com/assets/2193314/15760084/816ab9b0-28c6-11e6-8262-e26f7e994a58.png) +",2016-06-02 20:33:05 +178,"@@ -41,6 +41,14 @@ configurationRegistry.registerConfiguration({ + 'terminal.integrated.fontFamily': { + 'description': nls.localize('terminal.integrated.fontFamily', ""The font family used by the terminal (CSS font-family format), this defaults to editor.fontFamily's value.""), + 'type': 'string' ++ }, ++ 'terminal.integrated.fontSize': { ++ 'description': nls.localize('terminal.integrated.fontSize', ""The font size used by the terminal (in pixels), this defaults to editor.fontSize's value.""),","Sorry but let's go for consistency with the editor settings for this in commonEditorConfig.ts: + +``` +""Controls the font family of the terminal."" +""Controls the font size of the terminal."" +""Controls the line height of the terminal."" +``` +",2016-06-02 20:37:43 +176,"@@ -41,6 +41,14 @@ configurationRegistry.registerConfiguration({ + 'terminal.integrated.fontFamily': { + 'description': nls.localize('terminal.integrated.fontFamily', ""The font family used by the terminal (CSS font-family format), this defaults to editor.fontFamily's value.""), + 'type': 'string' ++ }, ++ 'terminal.integrated.fontSize': { ++ 'description': nls.localize('terminal.integrated.fontSize', ""The font size used by the terminal (in pixels), this defaults to editor.fontSize's value.""), ++ 'type': 'number' ++ }, ++ 'terminal.integrated.lineHeight': {","Same here, it needs the default set. +",2016-06-02 20:33:24 +161,"@@ -41,6 +41,14 @@ configurationRegistry.registerConfiguration({ + 'terminal.integrated.fontFamily': { + 'description': nls.localize('terminal.integrated.fontFamily', ""The font family used by the terminal (CSS font-family format), this defaults to editor.fontFamily's value.""), + 'type': 'string' ++ }, ++ 'terminal.integrated.fontSize': { ++ 'description': nls.localize('terminal.integrated.fontSize', ""The font size used by the terminal.""),","Add: "" (in pixels)"" +",2016-06-02 06:45:23 +162,"@@ -41,6 +41,14 @@ configurationRegistry.registerConfiguration({ + 'terminal.integrated.fontFamily': { + 'description': nls.localize('terminal.integrated.fontFamily', ""The font family used by the terminal (CSS font-family format), this defaults to editor.fontFamily's value.""), + 'type': 'string' ++ }, ++ 'terminal.integrated.fontSize': { ++ 'description': nls.localize('terminal.integrated.fontSize', ""The font size used by the terminal.""), ++ 'type': 'number' ++ }, ++ 'terminal.integrated.lineHeight': { ++ 'description': nls.localize('terminal.integrated.lineHeight', ""The line height used by the terminal.""),","Add: "" (in pixels)"" +",2016-06-02 06:45:26 +976,"@@ -41,6 +44,20 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope + * File a bug in [GitHub Issues](https://github.com/Microsoft/vscode/issues). + * [Tweet](https://twitter.com/code) us with other feedback. + ++## Related Products ++Microsoft is distributing its own build as Microsoft Visual Studio Code. ++You can download packages for Windows, Mac and Linux on [VS Code's website](https://code.visualstudio.com/Download). ++ ++It's based on Code Open Source with some changes: ++* Microsoft branding ++* licensed under Microsoft [closed source custom product license](https://code.visualstudio.com/License) (EULA) ++* Extension Marketplace supported ++* crash reporting and telemetry enabled",maybe add that both can be disabled?,2017-06-16 15:49:42 +973,"@@ -41,6 +44,20 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope + * File a bug in [GitHub Issues](https://github.com/Microsoft/vscode/issues). + * [Tweet](https://twitter.com/code) us with other feedback. + ++## Related Products ++Microsoft is distributing its own build as Microsoft Visual Studio Code. ++You can download packages for Windows, Mac and Linux on [VS Code's website](https://code.visualstudio.com/Download). ++ ++It's based on Code Open Source with some changes: ++* Microsoft branding ++* licensed under Microsoft [closed source custom product license](https://code.visualstudio.com/License) (EULA) ++* Extension Marketplace supported ++* crash reporting and telemetry enabled ++* user configuration and extensions stored in different directory then Code - Open Source",Typo: s/then/than/,2017-06-15 03:29:21 +827,"@@ -41,6 +65,7 @@ suite('Workbench - TerminalLinkHandler', () => { + testLink('c:/a/long/path'); + testLink('c:\\a\\long\\path'); + testLink('c:\\mixed/slash\\path'); ++ testLink('a/relative/path');","Will this also linkify just plain words for example `""foo""`? That way after validation the output of `ls` should all be linked. If so a test for that would be great.",2017-03-14 18:40:53 +343,"@@ -410,14 +410,19 @@ export class QuickOpenWidget implements IModelProvider { + + // Trigger open of element on selection + if (this.isVisible()) { +- const context: IEntryRunContext = { event, keymods: this.extractKeyMods(event), quickNavigateConfiguration: this.quickNavigateConfiguration }; ++ let eventForContext = event; + let mode = Mode.OPEN; + +- if (context.event instanceof StandardKeyboardEvent) { +- if (context.event.keyCode === KeyCode.RightArrow) { ++ if (event instanceof StandardKeyboardEvent) { ++ eventForContext = event.browserEvent;","@bpasero preserving the browser's event as the context here. will this work better? allows us to leave `Mode` logic in `elementSelected`. +",2016-10-18 17:03:27 +840,"@@ -411,6 +411,10 @@ export class EndOfLineEdit { + static readonly CRLF: EndOfLineEdit = Object.freeze({ newEol: EndOfLine.CRLF }); + + newEol: EndOfLine; ++ ++ constructor(newEol: EndOfLine) {","Any reason you didn't do: +```ts +constructor(public newEol: EndOfLine) { +} +``` +Is it because there would be an empty function body?",2017-03-21 17:40:03 +340,"@@ -411,7 +411,15 @@ export class QuickOpenWidget implements IModelProvider { + // Trigger open of element on selection + if (this.isVisible()) { + const context: IEntryRunContext = { event, keymods: this.extractKeyMods(event), quickNavigateConfiguration: this.quickNavigateConfiguration }; +- hide = this.model.runner.run(value, Mode.OPEN, context); ++ let mode = Mode.OPEN; ++ ++ if (context.event instanceof KeyboardEvent) {","@wprater can we just send over a flag to indicate this mode from where we call this method with the arrow key right pressed? I think we already create the standard keyboard event there and do not need to create it again here. +",2016-10-18 09:38:22 +68,"@@ -414,6 +424,14 @@ export class Model extends ee.EventEmitter implements debug.IModel { + this.emit(debug.ModelEvents.CALLSTACK_UPDATED); + } + ++ public continueThreads(): void {","I could add the functionality of `continueThreads` to `clearThreads` behind yet another boolean arguments. + +I think having an explicit method is better (`clearThreads` is already confusing enough). Let me know what you think. +",2016-03-16 02:49:32 +707,"@@ -416,65 +496,94 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient + } + + const shippedVersion = this.getTypeScriptVersion(this.globalTypescriptPath); +- const localModulePath = path.join(workspace.rootPath, 'node_modules', 'typescript', 'lib', 'tsserver.js'); ++ const localModulePath = this.localTypeScriptPath; + +- let messageShown: Thenable; +- if (fs.existsSync(localModulePath) && this.getTypeScriptVersion(localModulePath)) { ++ let messageShown: Thenable; ++ if (localModulePath) { + const localVersion = this.getTypeScriptVersion(localModulePath); + const usingWorkspaceVersion = this.workspaceState.get(TypeScriptServiceClient.useWorkspaceTsdkStorageKey, false); +- messageShown = window.showInformationMessage( +- usingWorkspaceVersion +- ? localize( +- 'usingWorkspaceTsVersion', +- 'Using TypeScript version {0} from workspace for IntelliSense.', +- localVersion) +- : localize( +- 'usingVSCodeTsVersion', +- 'Using VSCode\'s TypeScript version {0} for IntelliSense.', +- shippedVersion +- ), ++ messageShown = window.showQuickPick([ + { +- title: localize('use', 'Use workspace version ({0})', localVersion), ++ label: localize('useWorkspaceVersionOption', 'Use Workspace Version'), ++ description: localVersion || '', ++ detail: modulePath === localModulePath ? localize('activeVersion', 'active') : '',",I'd omit the `active` indication. It's not adding additional information as all information is already in the place holder text.,2017-01-27 02:26:35 +708,"@@ -416,65 +496,94 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient + } + + const shippedVersion = this.getTypeScriptVersion(this.globalTypescriptPath); +- const localModulePath = path.join(workspace.rootPath, 'node_modules', 'typescript', 'lib', 'tsserver.js'); ++ const localModulePath = this.localTypeScriptPath; + +- let messageShown: Thenable; +- if (fs.existsSync(localModulePath) && this.getTypeScriptVersion(localModulePath)) { ++ let messageShown: Thenable; ++ if (localModulePath) { + const localVersion = this.getTypeScriptVersion(localModulePath); + const usingWorkspaceVersion = this.workspaceState.get(TypeScriptServiceClient.useWorkspaceTsdkStorageKey, false); +- messageShown = window.showInformationMessage( +- usingWorkspaceVersion +- ? localize( +- 'usingWorkspaceTsVersion', +- 'Using TypeScript version {0} from workspace for IntelliSense.', +- localVersion) +- : localize( +- 'usingVSCodeTsVersion', +- 'Using VSCode\'s TypeScript version {0} for IntelliSense.', +- shippedVersion +- ), ++ messageShown = window.showQuickPick([ + { +- title: localize('use', 'Use workspace version ({0})', localVersion), ++ label: localize('useWorkspaceVersionOption', 'Use Workspace Version'), ++ description: localVersion || '', ++ detail: modulePath === localModulePath ? localize('activeVersion', 'active') : '', + id: MessageAction.useLocal + }, { +- title: localize( +- 'useVSCodeVersionOption', +- 'Use VSCode\'s version ({0})', +- shippedVersion), ++ label: localize('useVSCodeVersionOption', 'Use VSCode\'s Version'), ++ description: shippedVersion || '', ++ detail: modulePath === this.globalTypescriptPath ? localize('activeVersion', 'active') : '',",I'd omit the `active` indication. It's not adding additional information as all information is already in the place holder text.,2017-01-27 02:26:47 +705,"@@ -416,65 +496,94 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient + } + + const shippedVersion = this.getTypeScriptVersion(this.globalTypescriptPath); +- const localModulePath = path.join(workspace.rootPath, 'node_modules', 'typescript', 'lib', 'tsserver.js'); ++ const localModulePath = this.localTypeScriptPath; + +- let messageShown: Thenable; +- if (fs.existsSync(localModulePath) && this.getTypeScriptVersion(localModulePath)) { ++ let messageShown: Thenable; ++ if (localModulePath) { + const localVersion = this.getTypeScriptVersion(localModulePath); + const usingWorkspaceVersion = this.workspaceState.get(TypeScriptServiceClient.useWorkspaceTsdkStorageKey, false); +- messageShown = window.showInformationMessage( +- usingWorkspaceVersion +- ? localize( +- 'usingWorkspaceTsVersion', +- 'Using TypeScript version {0} from workspace for IntelliSense.', +- localVersion) +- : localize( +- 'usingVSCodeTsVersion', +- 'Using VSCode\'s TypeScript version {0} for IntelliSense.', +- shippedVersion +- ), ++ messageShown = window.showQuickPick([ + { +- title: localize('use', 'Use workspace version ({0})', localVersion), ++ label: localize('useWorkspaceVersionOption', 'Use Workspace Version'), ++ description: localVersion || '', ++ detail: modulePath === localModulePath ? localize('activeVersion', 'active') : '', + id: MessageAction.useLocal + }, { +- title: localize( +- 'useVSCodeVersionOption', +- 'Use VSCode\'s version ({0})', +- shippedVersion), ++ label: localize('useVSCodeVersionOption', 'Use VSCode\'s Version'), ++ description: shippedVersion || '', ++ detail: modulePath === this.globalTypescriptPath ? localize('activeVersion', 'active') : '', + id: MessageAction.useBundled, + }, { +- title: localize('learnMore', 'Learn More'), +- id: MessageAction.learnMore, +- isCloseAffordance: true ++ label: localize('learnMore', 'Learn More'), ++ description: '', ++ id: MessageAction.learnMore ++ }], { ++ placeHolder: usingWorkspaceVersion ++ ? localize( ++ 'usingWorkspaceTsVersion', ++ 'Using TypeScript version {0} from workspace for Typescript language features.',",Please use `TypeScript` rather than `Typescript`.,2017-01-27 02:24:57 +706,"@@ -416,65 +496,94 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient + } + + const shippedVersion = this.getTypeScriptVersion(this.globalTypescriptPath); +- const localModulePath = path.join(workspace.rootPath, 'node_modules', 'typescript', 'lib', 'tsserver.js'); ++ const localModulePath = this.localTypeScriptPath; + +- let messageShown: Thenable; +- if (fs.existsSync(localModulePath) && this.getTypeScriptVersion(localModulePath)) { ++ let messageShown: Thenable; ++ if (localModulePath) { + const localVersion = this.getTypeScriptVersion(localModulePath); + const usingWorkspaceVersion = this.workspaceState.get(TypeScriptServiceClient.useWorkspaceTsdkStorageKey, false); +- messageShown = window.showInformationMessage( +- usingWorkspaceVersion +- ? localize( +- 'usingWorkspaceTsVersion', +- 'Using TypeScript version {0} from workspace for IntelliSense.', +- localVersion) +- : localize( +- 'usingVSCodeTsVersion', +- 'Using VSCode\'s TypeScript version {0} for IntelliSense.', +- shippedVersion +- ), ++ messageShown = window.showQuickPick([ + { +- title: localize('use', 'Use workspace version ({0})', localVersion), ++ label: localize('useWorkspaceVersionOption', 'Use Workspace Version'), ++ description: localVersion || '', ++ detail: modulePath === localModulePath ? localize('activeVersion', 'active') : '', + id: MessageAction.useLocal + }, { +- title: localize( +- 'useVSCodeVersionOption', +- 'Use VSCode\'s version ({0})', +- shippedVersion), ++ label: localize('useVSCodeVersionOption', 'Use VSCode\'s Version'), ++ description: shippedVersion || '', ++ detail: modulePath === this.globalTypescriptPath ? localize('activeVersion', 'active') : '', + id: MessageAction.useBundled, + }, { +- title: localize('learnMore', 'Learn More'), +- id: MessageAction.learnMore, +- isCloseAffordance: true ++ label: localize('learnMore', 'Learn More'), ++ description: '', ++ id: MessageAction.learnMore ++ }], { ++ placeHolder: usingWorkspaceVersion ++ ? localize( ++ 'usingWorkspaceTsVersion', ++ 'Using TypeScript version {0} from workspace for Typescript language features.', ++ localVersion) ++ : localize( ++ 'usingVSCodeTsVersion', ++ 'Using VSCode\'s TypeScript version {0} for Typescript language features.',",Should use `TypeScript` rather than `Typescript`,2017-01-27 02:25:09 +709,"@@ -416,65 +496,94 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient + } + + const shippedVersion = this.getTypeScriptVersion(this.globalTypescriptPath); +- const localModulePath = path.join(workspace.rootPath, 'node_modules', 'typescript', 'lib', 'tsserver.js'); ++ const localModulePath = this.localTypeScriptPath; + +- let messageShown: Thenable; +- if (fs.existsSync(localModulePath) && this.getTypeScriptVersion(localModulePath)) { ++ let messageShown: Thenable; ++ if (localModulePath) { + const localVersion = this.getTypeScriptVersion(localModulePath); + const usingWorkspaceVersion = this.workspaceState.get(TypeScriptServiceClient.useWorkspaceTsdkStorageKey, false); +- messageShown = window.showInformationMessage( +- usingWorkspaceVersion +- ? localize( +- 'usingWorkspaceTsVersion', +- 'Using TypeScript version {0} from workspace for IntelliSense.', +- localVersion) +- : localize( +- 'usingVSCodeTsVersion', +- 'Using VSCode\'s TypeScript version {0} for IntelliSense.', +- shippedVersion +- ), ++ messageShown = window.showQuickPick([ + { +- title: localize('use', 'Use workspace version ({0})', localVersion), ++ label: localize('useWorkspaceVersionOption', 'Use Workspace Version'), ++ description: localVersion || '', ++ detail: modulePath === localModulePath ? localize('activeVersion', 'active') : '', + id: MessageAction.useLocal + }, { +- title: localize( +- 'useVSCodeVersionOption', +- 'Use VSCode\'s version ({0})', +- shippedVersion), ++ label: localize('useVSCodeVersionOption', 'Use VSCode\'s Version'), ++ description: shippedVersion || '', ++ detail: modulePath === this.globalTypescriptPath ? localize('activeVersion', 'active') : '', + id: MessageAction.useBundled, + }, { +- title: localize('learnMore', 'Learn More'), +- id: MessageAction.learnMore, +- isCloseAffordance: true ++ label: localize('learnMore', 'Learn More'), ++ description: '', ++ id: MessageAction.learnMore ++ }], { ++ placeHolder: usingWorkspaceVersion ++ ? localize( ++ 'usingWorkspaceTsVersion', ++ 'Using TypeScript version {0} from workspace for Typescript language features.', ++ localVersion) ++ : localize( ++ 'usingVSCodeTsVersion', ++ 'Using VSCode\'s TypeScript version {0} for Typescript language features.', ++ shippedVersion), + }); + } else { +- messageShown = window.showInformationMessage( +- localize( +- 'versionCheckUsingBundledTS', +- 'Using VSCode\'s TypeScript version {0} for IntelliSense.', +- shippedVersion), ++ messageShown = window.showQuickPick([ + { +- title: localize('learnMore', 'Learn More'), +- id: MessageAction.learnMore, +- isCloseAffordance: true, ++ label: localize('learnMore', 'Learn More'), ++ description: '', ++ ++ id: MessageAction.learnMore + }, { +- title: localize('close', 'Close'), +- id: MessageAction.close, +- isCloseAffordance: true, ++ label: localize('close', 'Close'), ++ description: '', ++ id: MessageAction.close ++ }], ++ { ++ placeHolder: localize( ++ 'versionCheckUsingBundledTS', ++ 'Using VSCode\'s TypeScript version {0} for Typescript language features.', ++ shippedVersion), + }); + } + ++ const tryShowRestart = (newModulePath: string) => { ++ if (newModulePath === this.modulePath) { ++ return; ++ } ++ ++ window.showInformationMessage( ++ localize('restartBlurb', 'Restart VSCode to apply change'),",We don't use `restart` anywhere else. I think we should use `Reload window to apply changes`.,2017-01-27 02:30:14 +229,"@@ -4164,6 +4167,33 @@ export var EventType = { + }; + + /** ++ * Positions on the view ++ */ ++export const ViewPosition = {","I suggest renaming `ViewPosition` to `MoveCommandViewPosition` or something more specific -- for someone looking at `monaco.d.ts` the current name might be very confusing, as it is simply typing an argument to a specific command and is not a new concept of `Position` <-> `ViewPosition`. +",2016-07-15 11:18:43 +227,"@@ -4164,6 +4167,33 @@ export var EventType = { + }; + + /** ++ * Positions on the view ++ */ ++export const ViewPosition = { ++ LineStart: 'lineStart', ++ LineFirstNonWhitespaceCharacter: 'lineFirstNonWhitespaceCharacter',","Sometimes referred to as ""soft start"". @jrieken @sandy081 -- would `lineSoftStart` be easier to program against? +",2016-07-15 11:16:46 +228,"@@ -4164,6 +4167,33 @@ export var EventType = { + }; + + /** ++ * Positions on the view ++ */ ++export const ViewPosition = { ++ LineStart: 'lineStart', ++ LineFirstNonWhitespaceCharacter: 'lineFirstNonWhitespaceCharacter', ++ LineCenter: 'lineCenter', ++ LineEnd: 'lineEnd', ++ LineLastNonWhitespaceCharacter: 'lineLastNonWhitespaceCharacter'","Same as above, `lineSoftEnd` -- would that be confusing? +",2016-07-15 11:17:09 +225,"@@ -4164,6 +4167,33 @@ export var EventType = { + }; + + /** ++ * Positions on the view ++ */ ++export const ViewPosition = { ++ LineStart: 'lineStart', ++ LineFirstNonWhitespaceCharacter: 'lineFirstNonWhitespaceCharacter', ++ LineCenter: 'lineCenter', ++ LineEnd: 'lineEnd', ++ LineLastNonWhitespaceCharacter: 'lineLastNonWhitespaceCharacter' ++}; ++ ++/** ++ * @internal ++ */ ++export var CommandDescription= {","space before = +",2016-07-15 11:13:54 +226,"@@ -4164,6 +4167,33 @@ export var EventType = { + }; + + /** ++ * Positions on the view ++ */ ++export const ViewPosition = { ++ LineStart: 'lineStart', ++ LineFirstNonWhitespaceCharacter: 'lineFirstNonWhitespaceCharacter', ++ LineCenter: 'lineCenter', ++ LineEnd: 'lineEnd', ++ LineLastNonWhitespaceCharacter: 'lineLastNonWhitespaceCharacter' ++}; ++ ++/** ++ * @internal ++ */ ++export var CommandDescription= { ++ CursorMove: { ++ description: nls.localize('editorCommand.cursorMove.description', ""Move cursor to a logical position in the view""), ++ args: [ ++ {","@jrieken Is this correct? I think the name and description should apply to `firstArgument.to` not to `firstArgument`. +",2016-07-15 11:15:35 +159,"@@ -42,6 +42,26 @@ configurationRegistry.registerConfiguration({ + 'description': nls.localize('terminal.integrated.fontFamily', ""The font family used by the terminal (CSS font-family format).""), + 'type': 'string', + 'default': 'Menlo, Monaco, Consolas, ""Droid Sans Mono"", ""Courier New"", monospace, ""Droid Sans Fallback""' ++ }, ++ 'terminal.integrated.fontSize': { ++ 'description': nls.localize('terminal.integrated.fontSize', ""The font size used by the terminal (CSS font-size format).""), ++ 'type': 'string', ++ 'default': '' ++ }, ++ 'terminal.integrated.lineHeight': { ++ 'description': nls.localize('terminal.integrated.lineHeight', ""The line height used by the terminal (CSS line height format).""), ++ 'type': 'string', ++ 'default': '' ++ }, ++ 'terminal.integrated.charWidth': {","I think https://github.com/Microsoft/vscode/issues/6456 should be figured out before the font size and line height is added to prevent addition the `charWidth`/`charHeight` settings. +",2016-05-28 20:51:32 +553,"@@ -42,6 +42,7 @@ export interface IEnvironmentService { + + execPath: string; + appRoot: string; ++ vscodeWindowId: string;","@Tyriar we cannot really add this here because environment service is agnostic to windows, we have one in the shared process as well as the CLI. I suggest to put this into the `IWindowService` on the renderer side.",2016-12-01 16:29:03 +989,"@@ -422,4 +423,13 @@ export function registerCommands(): void { + return void 0; + }); + }); ++ ++ CommandsRegistry.registerCommand('_workbench.quickOpen', function (accessor: ServicesAccessor, args: [string, IShowOptions]) { ++ const quickOpenService = accessor.get(IQuickOpenService);",Remove `IShowOptions`,2017-06-19 10:40:16 +360,"@@ -424,6 +435,10 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic + } + } + ++ private isEditorEagerlyPreviewing(editor: IBaseEditor): boolean {","@wprater why is this method needed? We already have the `block()` method for this purpose and should only rely on that. +",2016-10-21 09:53:51 +744,"@@ -424,6 +450,36 @@ class MouseDownOperation extends Disposable { + // Overwrite the detail of the MouseEvent, as it will be sent out in an event and contributions might rely on it. + e.detail = this._mouseState.count; + ++ if (!this._mouseState.altKey // we don't support multiple mouse",We should also include a test for an editor option here. `editor.dragAndDrop` or something... `this._context.configuration.editor` is available in this class.,2017-02-20 11:28:17 +741,"@@ -424,6 +450,36 @@ class MouseDownOperation extends Disposable { + // Overwrite the detail of the MouseEvent, as it will be sent out in an event and contributions might rely on it. + e.detail = this._mouseState.count; + ++ if (!this._mouseState.altKey // we don't support multiple mouse ++ && e.detail < 2 // only single click on a selection can work ++ && !this._isActive // the mouse is not down yet ++ && !this._currentSelection.isEmpty() // we don't drag single cursor ++ && this._currentSelection.containsPosition(position.position) // single click on a selection ++ ) { ++ this._isActive = true; ++ this._dropTarget = this._createMouseTarget(e, true);",This is where `this._mouseState.setMouseDownEvent('drag');` should be set,2017-02-20 11:10:51 +742,"@@ -424,6 +450,36 @@ class MouseDownOperation extends Disposable { + // Overwrite the detail of the MouseEvent, as it will be sent out in an event and contributions might rely on it. + e.detail = this._mouseState.count; + ++ if (!this._mouseState.altKey // we don't support multiple mouse ++ && e.detail < 2 // only single click on a selection can work ++ && !this._isActive // the mouse is not down yet ++ && !this._currentSelection.isEmpty() // we don't drag single cursor ++ && this._currentSelection.containsPosition(position.position) // single click on a selection ++ ) { ++ this._isActive = true; ++ this._dropTarget = this._createMouseTarget(e, true); ++ ++ this._mouseMoveMonitor.startMonitoring( ++ createMouseMoveEventMerger(null), ++ this._mouseDragThenMoveEventHandler.handler, ++ () => { ++ if (this._mouseState.lastMouseDownEvent !== 'drag') {","when can this happen? + +IMHO the mouseState is set to `drag` or `mouseDown` and it should not change while the mouse is pressed (i.e. while the global mouse monitoring is active). ",2017-02-20 11:11:55 +891,"@@ -425,11 +431,20 @@ export class VSCodeWindow { + } + + private onConfigurationUpdated(config: IConfiguration): void { +- const newMenuBarVisibility = this.getMenuBarVisibility(config); ++ const newMenuBarVisibility = this.getMenuBarVisibility(); + if (newMenuBarVisibility !== this.currentMenuBarVisibility) { + this.currentMenuBarVisibility = newMenuBarVisibility; + this.setMenuBarVisibility(newMenuBarVisibility); + } ++ ++ // Swipe command support (macOS) ++ const workbenchConfig = this.configurationService.getConfiguration(); ++ if (workbenchConfig && workbenchConfig.workbench && workbenchConfig.workbench.editor.swipeBetweenOpenFiles) {","Careful here, `workbenchConfig.workbench.editor` can be `null` so we need another `null` check.",2017-04-18 05:52:20 +490,"@@ -426,6 +430,11 @@ export class VSCodeWindow { + delete configuration.filesToCreate; + delete configuration.filesToDiff; + ++ // Update untitled files to restore so they come through in the reloaded window","@Tyriar I am thinking more and more that untitled editors with backups should not be loaded from the main side but rather from the window itself. Files for example restore because we store their state into local storage (via `IEditorInputFactory` - see https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/common/editor/editorStacksModel.ts#L621). + +If we add a factory for untitled editors, we would just rely on that to bring the untitled back on reopen. It would also fix the issue that untitled would reopen at the right location where they where before. +",2016-11-15 05:58:48 +464,"@@ -426,6 +430,11 @@ export class VSCodeWindow { + delete configuration.filesToCreate; + delete configuration.filesToDiff; + ++ // Update untitled files to restore so they come through in the reloaded window ++ configuration.untitledToRestore = this.backupService.getWorkspaceUntitledFileBackupsSync(Uri.file(configuration.workspacePath)).map(filePath => {","@Tyriar not a big fan of all the sync fs calls. Why can the state of backups not be in memory in the backup service? there should be no other process writing to the file or? +",2016-11-09 07:15:07 +465,"@@ -426,6 +430,11 @@ export class VSCodeWindow { + delete configuration.filesToCreate; + delete configuration.filesToDiff; + ++ // Update untitled files to restore so they come through in the reloaded window ++ configuration.untitledToRestore = this.backupService.getWorkspaceUntitledFileBackupsSync(Uri.file(configuration.workspacePath)).map(filePath => { ++ return { filePath: filePath };","@Tyriar TS allows you a nicer short hand syntax here: + +`return { filePath };` +",2016-11-09 07:15:32 +153,"@@ -43,12 +43,13 @@ export enum TokenType { + Resolution, + Comma, + Charset, +- + EscapedJavaScript, + BadEscapedJavaScript, + Comment, + SingleLineComment, + EOF, ++ Var,","we shouldn't have a special token for `var`. `var` should stay an identifier as there might be selectors of that name, or many other places where `var` is a valid identifier. +",2016-05-20 10:02:48 +339,"@@ -43,7 +43,8 @@ export interface IAutoFocus { + + export enum Mode { + PREVIEW, +- OPEN ++ OPEN, ++ OPEN_BEHIND","@wprater maybe better ""OPEN_IN_BACKGROUND""? +",2016-10-18 09:36:24 +687,"@@ -431,11 +430,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.ISession { + } + + private startServer(): TPromise { +- if (!this.adapter.program) { +- return TPromise.wrapError(new Error(nls.localize('noDebugAdapterExtensionInstalled', ""No extension installed for '{0}' debugging."", this.adapter.type))); +- } +- +- return this.getLaunchDetails().then(d => this.launchServer(d).then(() => { ++ return this.adapter.getAdapterExecutable().then(d => this.launchServer(d).then(() => {",`d` is the wrong acronym here,2017-01-18 14:11:21 +436,"@@ -438,8 +438,7 @@ export class VSCodeMenu { + private createOpenRecentMenuItem(path: string): Electron.MenuItem { + return new MenuItem({ + label: unMnemonicLabel(path), click: (menuItem, win, event) => { +- const openInNewWindow = event && ((!platform.isMacintosh && event.ctrlKey) || (platform.isMacintosh && event.metaKey)); +- const success = !!this.windowsService.open({ cli: this.environmentService.args, pathsToOpen: [path], forceNewWindow: openInNewWindow }); ++ const success = !!this.windowsService.open({ cli: this.environmentService.args, pathsToOpen: [path] });","@elemongw can we keep the semantic of forcing a new window when the user presses the Ctrl/Meta key? I see no reason to remove it. +",2016-11-03 07:30:40 +192,"@@ -44,20 +44,20 @@ + }, + { + ""name"": ""libchromiumcontent"", +- ""version"": ""49.0.2623.75"", ++ ""version"": ""51.0.2704.103"", + ""license"": ""MIT"", + ""repositoryURL"": ""https://github.com/electron/libchromiumcontent"", + ""isProd"": true + }, + { + ""name"": ""nodejs"", +- ""version"": ""5.10.0"", ++ ""version"": ""6.10.0"",","@bpasero, that's a bit wrong, isn't it? :cat: + +Current version Node.js: v6.2.2 +Current version Node.js in Electron: 6.1.0 +",2016-07-02 13:31:12 +173,"@@ -44,22 +42,23 @@ export class TerminalPanel extends Panel { + @IThemeService private themeService: IThemeService + ) { + super(TERMINAL_PANEL_ID, telemetryService); +- this.configurationHelper = new TerminalConfigHelper(platform.platform, this.configurationService, this.themeService); + this.toDispose = []; + } + + public layout(dimension: Dimension): void { +- let cols = Math.floor(this.parentDomElement.offsetWidth / TERMINAL_CHAR_WIDTH); +- let rows = Math.floor(this.parentDomElement.offsetHeight / TERMINAL_CHAR_HEIGHT); +- if (this.terminal) { +- this.terminal.resize(cols, rows); +- } +- if (this.ptyProcess.connected) { +- this.ptyProcess.send({ +- event: 'resize', +- cols: cols, +- rows: rows +- }); ++ if (this.font.charWidth && this.font.charHeight) {","Prefer early exits to keep indentation low: + +``` +if (!this.font.charWidth || !this.font.charHeight) { + return; +} +``` + +Also should this attempt to measure at this point or would that just be rework? +",2016-06-02 20:21:21 +777,"@@ -44,26 +41,22 @@ export default class MarkdownDocumentLinkProvider implements vscode.DocumentLink + return results; + } + +- private normalizeLink(link: string, base: string, toc: TableOfContentProvider): vscode.Uri { +- let uri = vscode.Uri.parse(link); +- if (!uri.scheme) { +- if (uri.fragment && !uri.path) { +- // local link +- const line = toc.lookup(uri.fragment); +- if (!isNaN(line)) { +- return vscode.Uri.parse(`command:revealLine?${encodeURIComponent(JSON.stringify({ lineNumber: line, at: 'top' }))}`); +- } +- } ++ private normalizeLink(document: vscode.TextDocument, link: string, base: string): vscode.Uri { ++ const uri = vscode.Uri.parse(link); ++ if (uri.scheme) { ++ return uri; ++ } + +- // assume it must be a file +- let file; +- if (uri.path[0] === '/') { +- file = path.join(vscode.workspace.rootPath, uri.path); +- } else { +- file = path.join(base, uri.path); +- } +- uri = vscode.Uri.file(file); ++ // assume it must be a file ++ let resourcePath; ++ if (!uri.path) { ++ resourcePath = document.uri.path; ++ } else if (uri.path[0] === '/') { ++ resourcePath = path.join(vscode.workspace.rootPath, uri.path); ++ } else { ++ resourcePath = path.join(base, uri.path); + } +- return uri; ++ ++ return vscode.Uri.parse(`command:_markdown.openDocumentLink?${encodeURIComponent(JSON.stringify({ fragment: uri.fragment, path: resourcePath }))}`);","This is a lot of code for using an URI that goes like this: `file:///files/thisFile.md#L22`. Unless there are bugs which I would happily fix, the `OpenerService` should handle such links correctly.",2017-02-24 11:39:50 +452,"@@ -440,6 +440,7 @@ export class EditorOptions implements IEditorOptions { + options.forceOpen = settings.forceOpen; + options.revealIfVisible = settings.revealIfVisible; + options.pinned = settings.pinned; ++ options.forcePreview = settings.forcePreview;","@wprater can you quickly check where else in this file options are handled, I think you missed to add this new flag e.g. to `TextDiffEditorOptions` +",2016-11-05 07:32:13 +285,"@@ -441,66 +441,81 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + // A save participant can still change the model now and since we are so close to saving + // we do not want to trigger another auto save or similar, so we block this + // In addition we update our version right after in case it changed because of a model change ++ let saveParticipantPromise = TPromise.as(versionId); ++ + if (TextFileEditorModel.saveParticipant) { +- this.blockModelContentChange = true; +- try { +- TextFileEditorModel.saveParticipant.participate(this, { isAutoSaved }); +- } finally { ++ saveParticipantPromise = TPromise.as(undefined).then(() => { ++ this.blockModelContentChange = true; ++ return TextFileEditorModel.saveParticipant.participate(this, { isAutoSaved }); ++ }).then(() => { + this.blockModelContentChange = false; +- } +- versionId = this.versionId; ++ return this.versionId; ++ }, err => { ++ this.blockModelContentChange = false; ++ return TPromise.wrapError(err);","@jrieken this is a semantical change from how it worked before where a save participant error would never make the save operation fail. maybe we should ignore the possible errors from save participants (especially since they can now come from extensions) and always allow the save to take place. +",2016-09-21 06:23:59 +286,"@@ -441,66 +441,81 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + // A save participant can still change the model now and since we are so close to saving + // we do not want to trigger another auto save or similar, so we block this + // In addition we update our version right after in case it changed because of a model change ++ let saveParticipantPromise = TPromise.as(versionId); ++ + if (TextFileEditorModel.saveParticipant) { +- this.blockModelContentChange = true; +- try { +- TextFileEditorModel.saveParticipant.participate(this, { isAutoSaved }); +- } finally { ++ saveParticipantPromise = TPromise.as(undefined).then(() => { ++ this.blockModelContentChange = true; ++ return TextFileEditorModel.saveParticipant.participate(this, { isAutoSaved }); ++ }).then(() => { + this.blockModelContentChange = false; +- } +- versionId = this.versionId; ++ return this.versionId; ++ }, err => { ++ this.blockModelContentChange = false; ++ return TPromise.wrapError(err); ++ }); + } + +- // Clear error flag since we are trying to save again +- this.inErrorMode = false; ++ this.mapPendingSaveToVersionId[versionId] = saveParticipantPromise.then(newVersionId => {","@jrieken is there a reason why you chose to store the save participant into `mapPendingSaveToVersionId`, then delete it and later store it in `mapPendingSaveToVersionId` again for the `updateContent` call? + +Easier to read and understand, I suggest to store the save participant promise into `mapPendingSaveToVersionId` as you do now, but do not delete it right after. Rather let the promise from `this.fileService.updateContent` also contribute to the overall pending save. + +In other words, a pending save is the sum of running save participants and saving to disk. +",2016-09-21 06:27:04 +287,"@@ -441,66 +441,81 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + // A save participant can still change the model now and since we are so close to saving + // we do not want to trigger another auto save or similar, so we block this + // In addition we update our version right after in case it changed because of a model change ++ let saveParticipantPromise = TPromise.as(versionId); ++ + if (TextFileEditorModel.saveParticipant) { +- this.blockModelContentChange = true; +- try { +- TextFileEditorModel.saveParticipant.participate(this, { isAutoSaved }); +- } finally { ++ saveParticipantPromise = TPromise.as(undefined).then(() => { ++ this.blockModelContentChange = true; ++ return TextFileEditorModel.saveParticipant.participate(this, { isAutoSaved }); ++ }).then(() => { + this.blockModelContentChange = false; +- } +- versionId = this.versionId; ++ return this.versionId; ++ }, err => { ++ this.blockModelContentChange = false; ++ return TPromise.wrapError(err); ++ }); + } + +- // Clear error flag since we are trying to save again +- this.inErrorMode = false; ++ this.mapPendingSaveToVersionId[versionId] = saveParticipantPromise.then(newVersionId => { + +- // Remember when this model was saved last +- this.lastSaveAttemptTime = Date.now(); +- +- // Save to Disk +- diag(`doSave(${versionId}) - before updateContent()`, this.resource, new Date()); +- this.mapPendingSaveToVersionId[versionId] = this.fileService.updateContent(this.versionOnDiskStat.resource, this.getValue(), { +- overwriteReadonly: overwriteReadonly, +- overwriteEncoding: overwriteEncoding, +- mtime: this.versionOnDiskStat.mtime, +- encoding: this.getEncoding(), +- etag: this.versionOnDiskStat.etag +- }).then((stat: IFileStat) => { +- diag(`doSave(${versionId}) - after updateContent()`, this.resource, new Date()); +- +- // Remove from pending saves ++ // remove save participant promise and update versionId with ++ // its new value (if pre-save changes happened) + delete this.mapPendingSaveToVersionId[versionId]; ++ versionId = newVersionId; + +- // Telemetry +- this.telemetryService.publicLog('filePUT', { mimeType: stat.mime, ext: paths.extname(this.versionOnDiskStat.resource.fsPath) }); ++ // Clear error flag since we are trying to save again ++ this.inErrorMode = false; + +- // Update dirty state unless model has changed meanwhile +- if (versionId === this.versionId) { +- diag(`doSave(${versionId}) - setting dirty to false because versionId did not change`, this.resource, new Date()); +- this.setDirty(false); +- } else { +- diag(`doSave(${versionId}) - not setting dirty to false because versionId did change meanwhile`, this.resource, new Date()); +- } ++ // Remember when this model was saved last ++ this.lastSaveAttemptTime = Date.now(); ++ ++ // Save to Disk ++ diag(`doSave(${versionId}) - before updateContent()`, this.resource, new Date()); ++ this.mapPendingSaveToVersionId[versionId] = this.fileService.updateContent(this.versionOnDiskStat.resource, this.getValue(), {","@jrieken as per my comment above I would here just return the promise and not add it to the map, since it is already added from the save participant. +",2016-09-21 06:27:33 +561,"@@ -441,7 +441,17 @@ export class WindowsManager implements IWindowsMainService { + } + + // Handle empty +- if (emptyToOpen.length > 0) { ++ if (emptyToRestore.length > 0) { ++ emptyToRestore.forEach(backupFolder => { ++ const configuration = this.toConfiguration(openConfig, null, null, null, null, backupFolder);","@Tyriar something is weird about `backupFolder`. As someone that tries to understand the code I would assume every window has an associated `backupFolder`. but that is not true, only the empty windows to restore have it. I would make this more obvious. Maybe remove the property from `IWindowConfiguration` and just pass it into `openInBrowserWindow` method? Also needs a clearer name to make its meaning more obvious.",2016-12-02 06:53:45 +558,"@@ -441,7 +441,17 @@ export class WindowsManager implements IWindowsMainService { + } + + // Handle empty +- if (emptyToOpen.length > 0) { ++ if (emptyToRestore.length > 0) { ++ emptyToRestore.forEach(backupFolder => { ++ const configuration = this.toConfiguration(openConfig, null, null, null, null, backupFolder); ++ const browserWindow = this.openInBrowserWindow(configuration, openInNewWindow, openInNewWindow ? void 0 : openConfig.windowToUse);","@Tyriar we always want each of these windows to open inside a new window so I suggest to just call + +`const browserWindow = this.openInBrowserWindow(configuration, true /* new window */);` + +In the same way as we do for restoring folders.",2016-12-02 06:43:30 +550,"@@ -441,7 +442,20 @@ export class WindowsManager implements IWindowsMainService { + } + + // Handle empty +- if (emptyToOpen.length > 0) { ++ if (emptyToRestore.length > 0) { ++ // TODO: There's an extra empty workspace opening when restoring an empty workspace (sometimes) ++ emptyToRestore.forEach(vscodeWindowId => { ++ const configuration = this.toConfiguration(openConfig); ++ configuration.vscodeWindowId = vscodeWindowId;",@Tyriar why is this done here and not inside the `toConfiguration` method?,2016-12-01 16:24:01 +562,"@@ -444,7 +444,7 @@ export class WindowsManager implements IWindowsMainService { + if (emptyToRestore.length > 0) { + emptyToRestore.forEach(emptyWorkspaceBackupFolder => { + const configuration = this.toConfiguration(openConfig, null, null, null, null); +- const browserWindow = this.openInBrowserWindow(configuration, openInNewWindow, openInNewWindow ? void 0 : openConfig.windowToUse, emptyWorkspaceBackupFolder); ++ const browserWindow = this.openInBrowserWindow(configuration, true /* new window */, openInNewWindow ? void 0 : openConfig.windowToUse, emptyWorkspaceBackupFolder);",@Tyriar I would not assume we have a `windowToUse` in this case ever?,2016-12-02 08:27:20 +57,"@@ -45,3 +29,25 @@ registerMode({ + moduleId: 'vs/workbench/parts/output/common/outputMode', + ctorName: 'OutputMode' + }); ++ ++// Register Output Panel ++(platform.Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor(","@isidorn do not forget to add the panel to the same buildfile.js where we added REPL so that the loader can load it +",2016-01-21 15:54:22 +58,"@@ -45,3 +29,25 @@ registerMode({ + moduleId: 'vs/workbench/parts/output/common/outputMode', + ctorName: 'OutputMode' + }); ++ ++// Register Output Panel ++(platform.Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( ++ 'vs/workbench/parts/output/browser/outputPanel', ++ 'OutputPanel', ++ OUTPUT_PANEL_ID, ++ nls.localize('output', ""Output""), ++ 'output', ++ 40","@isidorn I dont think we need the ""order"" property for panels, it is used for showing the actions in the activity bar only +",2016-01-21 15:55:43 +198,"@@ -45,6 +47,19 @@ KeybindingsRegistry.registerCommandDesc({ + + type ApiThemeClassName = 'vscode-light' | 'vscode-dark' | 'vscode-high-contrast'; + ++function isDefaultKeyboardEvent(e: KeyboardEvent): boolean { ++ let keyEvent = new StandardKeyboardEvent(e); ++ let keybinding = keyEvent.asKeybinding(); ++ switch (keybinding) { ++ case KeyMod.CtrlCmd | KeyCode.KEY_C: ++ case KeyMod.CtrlCmd | KeyCode.KEY_V: ++ case KeyMod.CtrlCmd | KeyCode.KEY_X: ++ case KeyMod.CtrlCmd | KeyCode.KEY_A:","this is bad +",2016-07-06 13:51:08 +500,"@@ -45,7 +42,7 @@ script: + - gulp electron + - gulp compile + - gulp optimize-vscode +- - if [[ ""$TRAVIS_OS_NAME"" == ""linux"" ]]; then ./scripts/test.sh --coverage; else ./scripts/test.sh; fi ++ - if [[ ""$TRAVIS_OS_NAME"" == ""linux"" ]]; then ./scripts/test.sh --no-colors --reporter dot --coverage; else ./scripts/test.sh --no-colors --reporter dot; fi",Awesome. Why take out the colors though? Red is what I usually look for when looking at travis.,2016-11-21 15:06:04 +205,"@@ -45,7 +49,7 @@ export class TerminalInstance { + this.xterm.on('data', (data) => { + this.terminalProcess.process.send({ + event: 'input', +- data: data ++ data: data && data.replace(TerminalInstance.eolRegex, os.EOL)","This should be split out above for clarity, it looks like it's passing in a boolean right now. +",2016-07-08 00:37:09 +557,"@@ -458,10 +458,10 @@ export class Workbench implements IPartService { + + // Backup File Service + const workspace = this.contextService.getWorkspace(); +- serviceCollection.set(IBackupFileService, this.instantiationService.createInstance(BackupFileService, workspace ? workspace.resource : null)); ++ serviceCollection.set(IBackupFileService, this.instantiationService.createInstance(BackupFileService, this.windowService.getCurrentWindowId()));",@Tyriar why not let backup file service depend on windows service to get the ID?,2016-12-02 06:40:03 +829,"@@ -46,18 +47,9 @@ export class ContextValuesContainer { + } + return ret; + } +- +- public fillInContext(bucket: any): void { +- if (this._parent) { +- this._parent.fillInContext(bucket); +- } +- for (let key in this._value) { +- bucket[key] = this._value[key]; +- } +- }","@joaomoreno I might be missing something but I don't find the place in which now child-context overwrites the values of it's parent. Like, a peek view editor which has `findWidgetVisible: false` and its parent editor/context having `findWidgetVisible: true`",2017-03-16 14:30:55 +371,"@@ -46,7 +45,7 @@ export class FileEditorInput extends CommonFileEditorInput { + @IHistoryService private historyService: IHistoryService, + @IEventService private eventService: IEventService, + @ITextFileService private textFileService: ITextFileService, +- @IBackupService private backupService: IBackupService ++ @IBackupFileService private backupFileService: IBackupFileService","Unused member +",2016-10-21 13:51:08 +293,"@@ -462,6 +471,10 @@ export abstract class TitleControl implements ITitleAreaControl { + actions.push(new Separator(), this.pinEditorAction); + } + ++ const titleBarMenu = this.menuService.createMenu(MenuId.EditorTab, this.contextKeyService);","Since you update the context key you don't need to create/dispose the menu as it will update when the context keys change. +",2016-10-04 10:50:56 +970,"@@ -462,7 +462,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { + const index = this.pinnedViewlets.indexOf(viewletId); + this.pinnedViewlets.splice(index, 1); + +- this.updateViewletSwitcher(); ++ if (this.viewletSwitcherBar) {",@nicksnyder should we not just move this check into the `updateViewletSwitcher` method? There are many more places where we call it.,2017-06-13 04:33:27 +640,"@@ -466,11 +466,20 @@ export class SnippetController { + return SnippetController.ID; + } + ++ public get inSnippetMode() { ++ return this._inSnippetMode.get(); ++ } ++ + public insertSnippet(template: string, overwriteBefore: number, overwriteAfter: number): void { + const snippet = CodeSnippet.fromTextmate(template, this._variableResolver); + this.run(snippet, overwriteBefore, overwriteAfter); + } + ++ public insertSnippetWithReplaceRange(template: string, replaceRange: Range): void {",We should try to get away with just using `insertSnippet`. The controller is already complex ,2016-12-21 08:23:13 +884,"@@ -47,47 +47,267 @@ class TestWorkspace implements IWorkspace { + suite('Workbench - TerminalLinkHandler', () => { + suite('localLinkRegex', () => { + test('Windows', () => { +- const regex = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null, null).localLinkRegex; +- function testLink(link: string) { +- assert.equal(` ${link} `.match(regex)[1], link); +- assert.equal(`:${link}:`.match(regex)[1], link); +- assert.equal(`;${link};`.match(regex)[1], link); +- assert.equal(`(${link})`.match(regex)[1], link); ++ const terminalLinkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Windows, null, null, null); ++ function testLink(link: string, linkUrl: string, lineNo?: string, columnNo?: string) { ++ assert.equal(terminalLinkHandler.extractLinkUrl(link), linkUrl); ++ assert.equal(terminalLinkHandler.extractLinkUrl(`:${link}:`), linkUrl); ++ assert.equal(terminalLinkHandler.extractLinkUrl(`;${link};`), linkUrl); ++ assert.equal(terminalLinkHandler.extractLinkUrl(`(${link})`), linkUrl); ++ ++ if (lineNo) { ++ const lineColumnInfo: LineColumnInfo = terminalLinkHandler.extractLineColumnInfo(link); ++ assert.equal(lineColumnInfo.lineNumber, lineNo); ++ ++ if (columnNo) { ++ assert.equal(lineColumnInfo.columnNumber, columnNo); ++ } ++ } + } +- testLink('c:\\foo'); +- testLink('c:/foo'); +- testLink('.\\foo'); +- testLink('./foo'); +- testLink('..\\foo'); +- testLink('../foo'); +- testLink('~\\foo'); +- testLink('~/foo'); +- testLink('c:/a/long/path'); +- testLink('c:\\a\\long\\path'); +- testLink('c:\\mixed/slash\\path'); +- testLink('a/relative/path'); ++ ++ testLink('c:\\foo', 'c:\\foo'); ++ testLink('c:/foo', 'c:/foo'); ++ testLink('.\\foo', '.\\foo'); ++ testLink('./foo', './foo'); ++ testLink('..\\foo', '..\\foo'); ++ testLink('../foo', '../foo'); ++ testLink('~\\foo', '~\\foo'); ++ testLink('~/foo', '~/foo'); ++ testLink('c:/a/long/path', 'c:/a/long/path'); ++ testLink('c:\\a\\long\\path', 'c:\\a\\long\\path'); ++ testLink('c:\\mixed/slash\\path', 'c:\\mixed/slash\\path'); ++ testLink('a/relative/path', 'a/relative/path'); ++ ++ // With line and column number. ++ testLink('c:\\foo:5', 'c:\\foo', '5'); ++ testLink('c:\\foo:5:3', 'c:\\foo', '5', '3'); ++ testLink('c:\\foo:line 5', 'c:\\foo', '5'); ++ testLink('c:\\foo:line 5, column 3', 'c:\\foo', '5', '3'); ++ testLink('c:\\foo(5)', 'c:\\foo', '5'); ++ testLink('c:\\foo(5,3)', 'c:\\foo', '5', '3'); ++ testLink('c:\\foo (5)', 'c:\\foo', '5'); ++ testLink('c:\\foo (5,3)', 'c:\\foo', '5', '3'); ++ testLink('c:\\foo on line 5', 'c:\\foo', '5'); ++ testLink('c:\\foo on line 5, column 3', 'c:\\foo', '5', '3'); ++ ++ testLink('c:/foo:5', 'c:/foo', '5'); ++ testLink('c:/foo:5:3', 'c:/foo', '5', '3'); ++ testLink('c:/foo:line 5', 'c:/foo', '5'); ++ testLink('c:/foo:line 5, column 3', 'c:/foo', '5', '3'); ++ testLink('c:/foo(5)', 'c:/foo', '5');",It would be good to have example programs that output each format (and only add them if we have an example).,2017-04-17 17:38:06 +958,"@@ -47,7 +47,7 @@ class ResourceModelCollection extends ReferenceCollection void 0);",Not sure if we should log here or add some other handler. We do add catch callbacks at higher levels that do error handling when the file does not exist. These still should be invoked after this change,2017-06-05 22:23:56 +386,"@@ -470,7 +492,11 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal + } + + // Activity Bar Part +- this.activitybar.getContainer().size(null, activityBarSize.height); ++ if (windowConfig && windowConfig.window.macOSUseInlineToolbar) {","Instead of duplicating the same code, the `activityBarSize` should be used in both cases. I know it was not used before but I do not think it would cause any harm. +",2016-10-24 14:18:58 +146,"@@ -477,9 +477,7 @@ export class SuggestWidget implements IContentWidget, IDisposable { + } + + private onModelModeChanged(): void { +- const model = this.editor.getModel(); +- const supports = SuggestRegistry.all(model); +- this.shouldShowEmptySuggestionList = supports.some(s => true); ++ this.shouldShowEmptySuggestionList = true;","all of this should be nuked. since the value of `shouldShowEmptySuggestionList` is now always true it should disappear, also we don't need to listen of mode change events anymore +",2016-05-03 09:12:27 +368,"@@ -479,6 +483,21 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe + + this.previousValue = prefix; + ++ // Track active editor before navigation","@wprater what about the picker? I think you need to extract this into a reusable method so that you can also use it when the picker opens. +",2016-10-21 10:02:45 +367,"@@ -479,6 +483,21 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe + + this.previousValue = prefix; + ++ // Track active editor before navigation ++ this.previousActiveEditorInput = this.editorService.getActiveEditorInput();","@wprater suggest to just use `activeGroup.activeEditor` here +",2016-10-21 10:01:58 +366,"@@ -479,6 +483,21 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe + + this.previousValue = prefix; + ++ // Track active editor before navigation ++ this.previousActiveEditorInput = this.editorService.getActiveEditorInput(); ++ ++ // Determine if there was a preview editor already open ++ this.previousPreviewEditorInput = null; ++ const activeGroup = this.editorGroupService.getStacksModel().activeGroup; ++ if (activeGroup) { ++ const visiblePreviewEditors = activeGroup.getEditors().filter((input: EditorInput) => {","@wprater why not just `activeGroup.previewEditor` ? +",2016-10-21 10:01:24 +144,"@@ -479,7 +479,7 @@ export class SuggestWidget implements IContentWidget, IDisposable { + private onModelModeChanged(): void { + const model = this.editor.getModel(); + const supports = SuggestRegistry.all(model); +- this.shouldShowEmptySuggestionList = supports.some(s => s.shouldShowEmptySuggestionList()); ++ this.shouldShowEmptySuggestionList = supports.some(s => true);","just set it to `true`, not need for `some` +",2016-05-02 10:13:38 +46,"@@ -48,33 +52,43 @@ interface ComputedStyles { + /** + * The workbench layout is responsible to lay out all parts that make the Monaco Workbench. + */ +-export class WorkbenchLayout implements IVerticalSashLayoutProvider { ++export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider { + +- private static sashWidthSettingsKey = 'workbench.sidebar.width'; ++ private static sashXWidthSettingsKey = 'workbench.sidebar.width'; ++ private static sashYHeightSettingsKey = 'workbench.panelpart.height';","=> workbench.panel.height +",2016-01-15 15:21:46 +47,"@@ -48,33 +52,43 @@ interface ComputedStyles { + /** + * The workbench layout is responsible to lay out all parts that make the Monaco Workbench. + */ +-export class WorkbenchLayout implements IVerticalSashLayoutProvider { ++export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider { + +- private static sashWidthSettingsKey = 'workbench.sidebar.width'; ++ private static sashXWidthSettingsKey = 'workbench.sidebar.width'; ++ private static sashYHeightSettingsKey = 'workbench.panelpart.height'; + + private parent: Builder; + private workbenchContainer: Builder; + private activitybar: Part; + private editor: Part; + private sidebar: Part; ++ private panelPart: Part; + private statusbar: Part; + private quickopen: QuickOpenController; + private options: LayoutOptions; + private toUnbind: { (): void; }[]; + private computedStyles: ComputedStyles; +- private editorHeight: number; + private workbenchSize: Dimension; +- private sash: Sash; ++ private sashX: Sash; ++ private sashY: Sash; + private startSidebarWidth: number; + private sidebarWidth: number; ++ private sidebarHeight: number; ++ private startPanelPartHeight: number;","@isidorn again easier to read the thing as ""panel"" unless you actually talk about the panelPart class. applies to multiple things in this file, not just here. +",2016-01-15 15:24:59 +643,"@@ -48,6 +48,28 @@ export class TypeOperations { + ); + } + ++ public static shiftIndent(config: CursorConfiguration, indentation: string, count?: number): string { ++ count = count || 1; ++ let desiredIndentCount = ShiftCommand.shiftIndentCount(indentation, indentation.length + count, config.tabSize); ++ let newIndentation = '';",What about `let newIndentation = '\t'.repeat(desiredIntentCount);`?,2016-12-23 04:18:53 +831,"@@ -48,6 +48,7 @@ ptyProcess.on('data', function (data) { + }); + + ptyProcess.on('exit', function (exitCode) { ++ ptyProcess.kill();","Thanks @chirag64! + +Does everything seem to work fine? It's worth testing on Windows if you haven't. I was thinking we might need a timeout here before we kill `terminalProcess` or it could mess with the pty processes' shutdown.",2017-03-19 07:10:51 +8,"@@ -48,6 +48,7 @@ var globals = (typeof self === 'object' ? self : global); + // IE: ""Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MS-RTC LM 8; InfoPath.3; Zune 4.7)"" + // Opera: ""Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.52"" + // FF: ""Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20100101 Firefox/8.0"" ++// Edge: ""Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246"" + ","I don't think we need that comment at the moment +",2015-11-21 19:09:25 +695,"@@ -48,6 +49,33 @@ export class ClearOutputAction extends Action { + } + } + ++export class ToggleOutputScrollLockAction extends Action { ++ ++ public static ID = 'workbench.output.action.toggleOutputScrollLock'; ++ public static LABEL = nls.localize('toggleOutputScrollLock', ""Toggle Output Scroll Lock""); ++ ++ private toDispose: IDisposable[] = []; ++ ++ constructor(id: string, label: string, ++ @IOutputService private outputService: IOutputService) { ++ super(id, label, 'output-action toggle-output-scroll-lock'); ++ this.toDispose.push(this.outputService.onActiveOutputChannel(channel => this._setChecked(this.outputService.getActiveChannel().hasScrollLock))); ++ } ++ ++ public run(): TPromise { ++ const activeChannel = this.outputService.getActiveChannel();","What if there is no active output channel (output hidden) and this command is triggered from the command pallete? +You either need a null check here or even better do not register this action as a global workbench action as I do not see people assigning shortcuts to this action or triggering it via command pallete.",2017-01-19 10:05:00 +492,"@@ -485,6 +510,9 @@ export class WindowsManager implements IWindowsMainService { + } + } + ++ // Register new paths for backup ++ this.backupService.pushWorkspaceBackupPathsSync(iPathsToOpen.filter(p => p.workspacePath).map(p => Uri.file(p.workspacePath)));","@Tyriar should this only happen if hot exit is enabled in settings? +",2016-11-15 06:00:44 +868,"@@ -488,6 +488,7 @@ export class TreeView extends HeightMap { + this.viewListeners.push(DOM.addDisposableListener(this.domNode, 'mousedown', (e) => this.onMouseDown(e))); + this.viewListeners.push(DOM.addDisposableListener(this.domNode, 'mouseup', (e) => this.onMouseUp(e))); + this.viewListeners.push(DOM.addDisposableListener(this.wrapper, 'click', (e) => this.onClick(e))); ++ this.viewListeners.push(DOM.addDisposableListener(this.wrapper, 'auxclick', (e) => this.onClick(e))); // >= Chrome 56","If AUXCLICK is getting disabled, why add an event listener for the event type?",2017-04-02 22:17:47 +87,"@@ -49,14 +72,41 @@ export class MacTerminalService implements ITerminalService { + child.on('exit', (code: number) => { + c(code === 0 ? 'iterm.scpt' : 'terminal.scpt'); + }); +- }).then(name => uri.parse(require.toUrl(`vs/workbench/parts/execution/electron-browser/${ name }`)).fsPath); ++ }).then(name => uri.parse(require.toUrl(`vs/workbench/parts/execution/electron-browser/${name}`)).fsPath); + } + } + + export class LinuxTerminalService implements ITerminalService { + public serviceId = ITerminalService; + ++ constructor( ++ @IConfigurationService private _configurationService: IConfigurationService ++ ) { } ++ ++ + public openTerminal(path: string): void { +- cp.spawn('x-terminal-emulator', [], { cwd: path }); ++ this._configurationService.loadConfiguration().done(configuration => { ++ return new Promise((success, failed) => { ++ this.spawnTerminal( ++ cp, ++ configuration, ++ path, ++ success, ++ err => { ++ errors.onUnexpectedError(err); ++ failed(err); ++ } ++ ); ++ }); ++ }, errors.onUnexpectedError); + } ++ ++ private spawnTerminal(spawner, configuration, path: string, onExit, onError) { ++ let terminalConfig = configuration.terminal; ++ let exec = terminalConfig.linux.exec || defaultLinuxTerm; ++ const child = spawner.spawn(exec, [], { cwd: path });","Does just setting the `cwd` work with `gnome-terminal`? You may need to pass in `--working-directory=path` for that? +",2016-03-24 01:40:03 +956,"@@ -49,7 +51,11 @@ export class MergeConflictParser { + } + + // Create a new conflict starting at this line +- currentConflict = { startHeader: line }; ++ currentConflict = { startHeader: line, commonAncestors: null }; ++ } ++ // Are we within a conflict block and is this a common ancestors marker? ||||||| ++ else if (currentConflict && line.text.startsWith(commonAncestorsMarker)) { ++ currentConflict.commonAncestors = line;","If, for some reason, we ended up with: + +``` +<<<<<<< HEAD +Foo +||||||| common +foo +||||||| common +fooo +======= +blah +>>>>>>> incoming +``` + +We will end up extending the ""current"" content over the first merge ancestor block. If we encounter two blocks of `|||||||` I think there are two thing we could do: + + - Favorable: Don't overwrite `currentConflict.commonAncestors`, just leave it with the first occurrence, this way the current content block will span the correct range. (e.g. `else if (currentConflict && !currentConflict.commonAncestors && line.text.startsWith(commonAncestorsMarker))` + - Break out of scanning (like we do if we encounter a start marker before an end marker), so we don't provide any decoration if we are unsure what to do. + +FWIW I think this is also true of existing `=======` scanning...",2017-05-30 16:09:15 +839,"@@ -490,6 +490,18 @@ export class Thread implements IThread { + }); + } + ++ /** ++ * Returns exception info promise if the exception was thrown and the debug adapter supports 'exceptionInfo' request, otherwise null ++ */ ++ public get exceptionInfo(): TPromise { ++ const session = this.process.session;","I would love if the exception widget always calls this method. +And all the logic is in this method, meaning that if we are not stopped we return null, if the session does not supportExceptionInfoRequest we also return something",2017-03-21 17:07:29 +844,"@@ -490,6 +490,18 @@ export class Thread implements IThread { + }); + } + ++ /** ++ * Returns exception info promise if the exception was thrown and the debug adapter supports 'exceptionInfo' request, otherwise null ++ */ ++ public get exceptionInfo(): TPromise { ++ const session = this.process.session; ++ if (session.capabilities.supportsExceptionInfoRequest && this.stoppedDetails && this.stoppedDetails.reason === 'exception') {","I do not like this check for this.stoppedDetails and this.stoppedDetails.reason === 'exception' since now we do it two times. Once before calling this method and once in the method. + +We should do it in only one of those places - whichever feels better to you. +You just have to figure out what is the contract of this method and when should it be calle",2017-03-22 10:55:40 +833,"@@ -490,6 +490,18 @@ export class Thread implements IThread { + }); + } + ++ /** ++ * Returns exception info promise if the exception was thrown and the debug adapter supports 'exceptionInfo' request, otherwise null ++ */ ++ public get exceptionInfo(): TPromise { ++ const session = this.process.session; ++ if (session.capabilities.supportsExceptionInfoRequest && this.stoppedDetails && this.stoppedDetails.reason === 'exception') { ++ return session.exceptionInfo({ threadId: this.threadId }); ++ } ++ ++ return null;","You can not just return `null` when a promise is expected, you should +`return TPromise.as(null)`",2017-03-21 17:00:23 +44,"@@ -499,6 +533,42 @@ export class Workbench implements IPartService { + this.storageService.store(Workbench.sidebarHiddenSettingKey, hidden ? 'true' : 'false', StorageScope.WORKSPACE); + } + ++ public isPanelPartHidden(): boolean {","@isidorn => isPanelHidden +",2016-01-15 15:19:03 +45,"@@ -499,6 +533,42 @@ export class Workbench implements IPartService { + this.storageService.store(Workbench.sidebarHiddenSettingKey, hidden ? 'true' : 'false', StorageScope.WORKSPACE); + } + ++ public isPanelPartHidden(): boolean { ++ return this.panelPartHidden; ++ } ++ ++ public setPanelPartHidden(hidden: boolean, skipLayout?:boolean): void {","@isidorn => setPanelHidden +",2016-01-15 15:19:17 +115,"@@ -5,14 +5,14 @@ + import fs = require('fs'); + import env = require('vs/base/common/platform'); + +-export let defaultLinuxTerm = 'x-terminal-emulator'; ++export let DEFAULT_LINUX_TERM = 'x-terminal-emulator'; + + // if we're not on debian and using gnome then + // set default to gnome-terminal + if (env.isLinux + && fs.existsSync('/etc/debian_version') === false + && process.env.DESKTOP_SESSION === 'gnome') { +- defaultLinuxTerm = 'gnome-terminal'; ++ DEFAULT_LINUX_TERM = 'gnome-terminal'; + } + +-export const defaultWindowsTerm = 'cmd'; +\ No newline at end of file ++export const DEFAILT_WINDOWS_TERM = 'cmd';","Typo DEFAULT +",2016-04-18 18:50:35 +692,"@@ -5,15 +5,17 @@ + 'use strict'; + + import { localize } from 'vs/nls'; +-import { WalkThroughInput } from 'vs/workbench/parts/walkThrough/common/walkThroughInput'; ++import { WalkThroughInput } from 'vs/workbench/parts/walkThrough/node/walkThroughInput'; + import { WalkThroughPart } from 'vs/workbench/parts/walkThrough/electron-browser/walkThroughPart'; ++import { WalkThroughContentProvider, WalkThroughSnippetContentProvider } from 'vs/workbench/parts/walkThrough/node/walkThroughContentProvider'; + import { EditorWalkThroughAction } from 'vs/workbench/parts/walkThrough/electron-browser/editor/editorWalkThrough'; + import { Registry } from 'vs/platform/platform'; + import { EditorDescriptor } from 'vs/workbench/browser/parts/editor/baseEditor'; + import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor'; + import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; + import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actionRegistry'; + import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; ++import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; + + (Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor(WalkThroughPart.ID,",`Registry.as(EditorExtensions.Editors)`,2017-01-19 06:01:05 +690,"@@ -5,16 +5,114 @@ + + 'use strict'; + +-let pageHeight = 0; +- +-window.onload = () => { +- pageHeight = document.body.getBoundingClientRect().height; +-}; +- +-window.addEventListener('resize', () => { +- const currentOffset = window.scrollY; +- const newPageHeight = document.body.getBoundingClientRect().height; +- const dHeight = newPageHeight / pageHeight; +- window.scrollTo(0, currentOffset * dHeight); +- pageHeight = newPageHeight; +-}, true); ++(function () { ++ var pageHeight = 0; ++ ++ /** ++ * Find the elements around line. ++ * ++ * If an exact match, returns a single element. If the line is between elements, ++ * returns the element before and the element after the given line. ++ */ ++ function getElementsAroundSourceLine(targetLine) { ++ const lines = document.getElementsByClassName('code-line'); ++ let before = null; ++ for (const element of lines) { ++ const lineNumber = +element.getAttribute('data-line'); ++ if (isNaN(lineNumber)) { ++ continue; ++ } ++ const entry = { line: lineNumber, element: element }; ++ if (lineNumber === targetLine) { ++ return { before: entry, after: null }; ++ } else if (lineNumber > targetLine) { ++ return { before, after: entry }; ++ } ++ before = entry; ++ } ++ return { before }; ++ } ++ ++ function getSourceRevealAddedOffset() { ++ return -(window.innerHeight * 1 / 5); ++ } ++ ++ /** ++ * Attempt to reveal the element for a source line in the editor. ++ */ ++ function scrollToRevealSourceLine(line) { ++ const {before, after} = getElementsAroundSourceLine(line); ++ if (before) { ++ let scrollTo = 0; ++ if (after) { ++ // Between two elements. Go to percentage offset between them. ++ const betweenProgress = (line - before.line) / (after.line - before.line); ++ const elementOffset = after.element.getBoundingClientRect().top - before.element.getBoundingClientRect().top; ++ scrollTo = before.element.getBoundingClientRect().top + betweenProgress * elementOffset; ++ } else { ++ scrollTo = before.element.getBoundingClientRect().top; ++ } ++ window.scroll(0, window.scrollY + scrollTo + getSourceRevealAddedOffset()); ++ } ++ } ++ ++ function didUpdateScrollPosition(offset) { ++ const lines = document.getElementsByClassName('code-line'); ++ let nearest = lines[0]; ++ for (let i = lines.length - 1; i >= 0; --i) { ++ const lineElement = lines[i]; ++ if (offset <= window.scrollY + lineElement.getBoundingClientRect().top + lineElement.getBoundingClientRect().height) { ++ nearest = lineElement; ++ } else { ++ break; ++ } ++ } ++ ++ if (nearest) { ++ const line = +nearest.getAttribute('data-line'); ++ const args = [window.initialData.source, line]; ++ window.parent.postMessage({ ++ command: ""did-click-link"",","This functionality is something we would probably want to standardize, similar to the `postMessage` command. Emulating clicks is pretty iffy.",2017-01-19 00:49:02 +488,"@@ -5,19 +5,18 @@ + + 'use strict'; + +-import Uri from 'vs/base/common/uri'; + import { EventEmitter } from 'events'; + import { ipcMain as ipc, app } from 'electron'; + import { TPromise, TValueCallback } from 'vs/base/common/winjs.base'; + import { ReadyState, VSCodeWindow } from 'vs/code/electron-main/window'; + import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +-import { IBackupMainService } from 'vs/platform/backup/common/backup'; + import { ILogService } from 'vs/code/electron-main/log'; + import { IStorageService } from 'vs/code/electron-main/storage'; + + const EventTypes = { +- BEFORE_QUIT: 'before-quit' ++ BEFORE_QUIT: 'before-quit', ++ AFTER_UNLOAD: 'after-unload'","@Tyriar should this maybe be `BEFORE_CLOSE`? because the next thing that is going to happen after this event is the window closing. +",2016-11-15 05:40:10 +544,"@@ -5,330 +5,178 @@ + + 'use strict'; + +-import * as strings from 'vs/base/common/strings'; ++import uri from 'vs/base/common/uri'; + +-import * as fs from 'fs'; ++import * as os from 'os'; + import * as path from 'path'; + +-import * as baseMime from 'vs/base/common/mime'; +-import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; +-import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; ++import * as ipc from 'vs/base/parts/ipc/common/ipc'; ++ ++import { IProgress } from 'vs/platform/search/common/search'; + import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +-import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding'; + import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; ++import { ISearchWorkerConfig, ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc'; + +-interface ReadLinesOptions { +- bufferLength: number; +- encoding: string; +-} ++import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; + + export class Engine implements ISearchEngine { + + private static PROGRESS_FLUSH_CHUNK_SIZE = 50; // optimization: number of files to process before emitting progress event + +- private rootFolders: string[]; +- private extraFiles: string[]; +- private maxResults: number; ++ private config: IRawSearch; + private walker: FileWalker; +- private contentPattern: RegExp; +- private isCanceled: boolean; +- private isDone: boolean; +- private total: number; +- private worked: number; +- private progressed: number; + private walkerError: Error; +- private walkerIsDone: boolean; +- private fileEncoding: string; +- private limitReached: boolean; ++ ++ private isCanceled = false; ++ private isDone = false; ++ private totalBytes = 0; ++ private processedBytes = 0; ++ private progressed = 0; ++ private walkerIsDone = false; ++ private limitReached = false; ++ private numResults = 0; ++ ++ private nextWorker = 0; ++ private workers: ISearchWorker[] = []; ++ private workerClients: Client[] = []; + + constructor(config: IRawSearch, walker: FileWalker) { +- this.rootFolders = config.rootFolders; +- this.extraFiles = config.extraFiles; ++ this.config = config; + this.walker = walker; +- this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); +- this.isCanceled = false; +- this.limitReached = false; +- this.maxResults = config.maxResults; +- this.worked = 0; +- this.progressed = 0; +- this.total = 0; +- this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8; + } + +- public cancel(): void { ++ cancel(): void { + this.isCanceled = true; + this.walker.cancel(); +- } + +- public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { +- let resultCounter = 0; ++ this.workers.forEach(w => w.cancel());",Add error handler to returned promises?,2016-11-30 19:50:40 +541,"@@ -5,330 +5,178 @@ + + 'use strict'; + +-import * as strings from 'vs/base/common/strings'; ++import uri from 'vs/base/common/uri'; + +-import * as fs from 'fs'; ++import * as os from 'os'; + import * as path from 'path'; + +-import * as baseMime from 'vs/base/common/mime'; +-import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; +-import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; ++import * as ipc from 'vs/base/parts/ipc/common/ipc'; ++ ++import { IProgress } from 'vs/platform/search/common/search'; + import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +-import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding'; + import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; ++import { ISearchWorkerConfig, ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc'; + +-interface ReadLinesOptions { +- bufferLength: number; +- encoding: string; +-} ++import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; + + export class Engine implements ISearchEngine { + + private static PROGRESS_FLUSH_CHUNK_SIZE = 50; // optimization: number of files to process before emitting progress event + +- private rootFolders: string[]; +- private extraFiles: string[]; +- private maxResults: number; ++ private config: IRawSearch; + private walker: FileWalker; +- private contentPattern: RegExp; +- private isCanceled: boolean; +- private isDone: boolean; +- private total: number; +- private worked: number; +- private progressed: number; + private walkerError: Error; +- private walkerIsDone: boolean; +- private fileEncoding: string; +- private limitReached: boolean; ++ ++ private isCanceled = false; ++ private isDone = false; ++ private totalBytes = 0; ++ private processedBytes = 0; ++ private progressed = 0; ++ private walkerIsDone = false; ++ private limitReached = false; ++ private numResults = 0; ++ ++ private nextWorker = 0; ++ private workers: ISearchWorker[] = []; ++ private workerClients: Client[] = []; + + constructor(config: IRawSearch, walker: FileWalker) { +- this.rootFolders = config.rootFolders; +- this.extraFiles = config.extraFiles; ++ this.config = config; + this.walker = walker; +- this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); +- this.isCanceled = false; +- this.limitReached = false; +- this.maxResults = config.maxResults; +- this.worked = 0; +- this.progressed = 0; +- this.total = 0; +- this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8; + } + +- public cancel(): void { ++ cancel(): void { + this.isCanceled = true; + this.walker.cancel(); +- } + +- public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { +- let resultCounter = 0; ++ this.workers.forEach(w => w.cancel()); ++ } + +- let progress = () => { +- this.progressed++; +- if (this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { +- onProgress({ total: this.total, worked: this.worked }); // buffer progress in chunks to reduce pressure ++ search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { ++ this.startWorkers(); ++ const progress = () => { ++ if (++this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { ++ onProgress({ total: this.totalBytes, worked: this.processedBytes }); // buffer progress in chunks to reduce pressure + } + }; + +- let unwind = (processed: number) => { +- this.worked += processed; ++ const unwind = (processed: number) => { ++ this.processedBytes += processed; + + // Emit progress() unless we got canceled or hit the limit + if (processed && !this.isDone && !this.isCanceled && !this.limitReached) { + progress(); + } + + // Emit done() +- if (this.worked === this.total && this.walkerIsDone && !this.isDone) { ++ if (!this.isDone && this.processedBytes === this.totalBytes && this.walkerIsDone) {","I wonder if `this.processedBytes === this.totalBytes` is a good condition to rely on. If a file changes its size between the file traversal and the text search it would never hold, would it?",2016-11-30 19:31:30 +545,"@@ -5,330 +5,178 @@ + + 'use strict'; + +-import * as strings from 'vs/base/common/strings'; ++import uri from 'vs/base/common/uri'; + +-import * as fs from 'fs'; ++import * as os from 'os'; + import * as path from 'path'; + +-import * as baseMime from 'vs/base/common/mime'; +-import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; +-import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; ++import * as ipc from 'vs/base/parts/ipc/common/ipc'; ++ ++import { IProgress } from 'vs/platform/search/common/search'; + import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +-import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding'; + import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; ++import { ISearchWorkerConfig, ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc'; + +-interface ReadLinesOptions { +- bufferLength: number; +- encoding: string; +-} ++import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; + + export class Engine implements ISearchEngine { + + private static PROGRESS_FLUSH_CHUNK_SIZE = 50; // optimization: number of files to process before emitting progress event + +- private rootFolders: string[]; +- private extraFiles: string[]; +- private maxResults: number; ++ private config: IRawSearch; + private walker: FileWalker; +- private contentPattern: RegExp; +- private isCanceled: boolean; +- private isDone: boolean; +- private total: number; +- private worked: number; +- private progressed: number; + private walkerError: Error; +- private walkerIsDone: boolean; +- private fileEncoding: string; +- private limitReached: boolean; ++ ++ private isCanceled = false; ++ private isDone = false; ++ private totalBytes = 0; ++ private processedBytes = 0; ++ private progressed = 0; ++ private walkerIsDone = false; ++ private limitReached = false; ++ private numResults = 0; ++ ++ private nextWorker = 0; ++ private workers: ISearchWorker[] = []; ++ private workerClients: Client[] = []; + + constructor(config: IRawSearch, walker: FileWalker) { +- this.rootFolders = config.rootFolders; +- this.extraFiles = config.extraFiles; ++ this.config = config; + this.walker = walker; +- this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); +- this.isCanceled = false; +- this.limitReached = false; +- this.maxResults = config.maxResults; +- this.worked = 0; +- this.progressed = 0; +- this.total = 0; +- this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8; + } + +- public cancel(): void { ++ cancel(): void { + this.isCanceled = true; + this.walker.cancel(); +- } + +- public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { +- let resultCounter = 0; ++ this.workers.forEach(w => w.cancel()); ++ } + +- let progress = () => { +- this.progressed++; +- if (this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { +- onProgress({ total: this.total, worked: this.worked }); // buffer progress in chunks to reduce pressure ++ search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { ++ this.startWorkers(); ++ const progress = () => { ++ if (++this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { ++ onProgress({ total: this.totalBytes, worked: this.processedBytes }); // buffer progress in chunks to reduce pressure + } + }; + +- let unwind = (processed: number) => { +- this.worked += processed; ++ const unwind = (processed: number) => { ++ this.processedBytes += processed; + + // Emit progress() unless we got canceled or hit the limit + if (processed && !this.isDone && !this.isCanceled && !this.limitReached) { + progress(); + } + + // Emit done() +- if (this.worked === this.total && this.walkerIsDone && !this.isDone) { ++ if (!this.isDone && this.processedBytes === this.totalBytes && this.walkerIsDone) { + this.isDone = true; ++ this.disposeWorkers();",Why is this different from cancel() above? Should the walker also be canceled/disposed?,2016-11-30 19:52:08 +546,"@@ -5,330 +5,178 @@ + + 'use strict'; + +-import * as strings from 'vs/base/common/strings'; ++import uri from 'vs/base/common/uri'; + +-import * as fs from 'fs'; ++import * as os from 'os'; + import * as path from 'path'; + +-import * as baseMime from 'vs/base/common/mime'; +-import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; +-import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; ++import * as ipc from 'vs/base/parts/ipc/common/ipc'; ++ ++import { IProgress } from 'vs/platform/search/common/search'; + import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +-import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding'; + import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; ++import { ISearchWorkerConfig, ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc'; + +-interface ReadLinesOptions { +- bufferLength: number; +- encoding: string; +-} ++import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; + + export class Engine implements ISearchEngine { + + private static PROGRESS_FLUSH_CHUNK_SIZE = 50; // optimization: number of files to process before emitting progress event + +- private rootFolders: string[]; +- private extraFiles: string[]; +- private maxResults: number; ++ private config: IRawSearch; + private walker: FileWalker; +- private contentPattern: RegExp; +- private isCanceled: boolean; +- private isDone: boolean; +- private total: number; +- private worked: number; +- private progressed: number; + private walkerError: Error; +- private walkerIsDone: boolean; +- private fileEncoding: string; +- private limitReached: boolean; ++ ++ private isCanceled = false; ++ private isDone = false; ++ private totalBytes = 0; ++ private processedBytes = 0; ++ private progressed = 0; ++ private walkerIsDone = false; ++ private limitReached = false; ++ private numResults = 0; ++ ++ private nextWorker = 0; ++ private workers: ISearchWorker[] = []; ++ private workerClients: Client[] = []; + + constructor(config: IRawSearch, walker: FileWalker) { +- this.rootFolders = config.rootFolders; +- this.extraFiles = config.extraFiles; ++ this.config = config; + this.walker = walker; +- this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); +- this.isCanceled = false; +- this.limitReached = false; +- this.maxResults = config.maxResults; +- this.worked = 0; +- this.progressed = 0; +- this.total = 0; +- this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8; + } + +- public cancel(): void { ++ cancel(): void { + this.isCanceled = true; + this.walker.cancel(); +- } + +- public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { +- let resultCounter = 0; ++ this.workers.forEach(w => w.cancel()); ++ } + +- let progress = () => { +- this.progressed++; +- if (this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { +- onProgress({ total: this.total, worked: this.worked }); // buffer progress in chunks to reduce pressure ++ search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { ++ this.startWorkers(); ++ const progress = () => { ++ if (++this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { ++ onProgress({ total: this.totalBytes, worked: this.processedBytes }); // buffer progress in chunks to reduce pressure + } + }; + +- let unwind = (processed: number) => { +- this.worked += processed; ++ const unwind = (processed: number) => { ++ this.processedBytes += processed; + + // Emit progress() unless we got canceled or hit the limit + if (processed && !this.isDone && !this.isCanceled && !this.limitReached) { + progress(); + } + + // Emit done() +- if (this.worked === this.total && this.walkerIsDone && !this.isDone) { ++ if (!this.isDone && this.processedBytes === this.totalBytes && this.walkerIsDone) { + this.isDone = true; ++ this.disposeWorkers(); + done(this.walkerError, { + limitHit: this.limitReached, + stats: this.walker.getStats() + }); + } + }; + +- // Walk over the file system +- this.walker.walk(this.rootFolders, this.extraFiles, result => { +- const size = result.size || 1; +- this.total += size; +- +- // If the result is empty or we have reached the limit or we are canceled, ignore it +- if (this.limitReached || this.isCanceled) { +- return unwind(size); +- } ++ const run = (batch: string[], batchBytes: number): void => { ++ const worker = this.workers[this.nextWorker]; ++ this.nextWorker = (this.nextWorker + 1) % this.workers.length; + +- // Indicate progress to the outside +- progress(); +- +- let fileMatch: FileMatch = null; +- +- let doneCallback = (error?: Error) => { +- if (!error && !this.isCanceled && fileMatch && !fileMatch.isEmpty()) { +- onResult(fileMatch.serialize()); +- } +- +- return unwind(size); +- }; +- +- const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath; +- let perLineCallback = (line: string, lineNumber: number) => { +- if (this.limitReached || this.isCanceled) { +- return; // return early if canceled or limit reached ++ const maxResults = this.config.maxResults - this.numResults; ++ worker.search({ absolutePaths: batch, maxResults }).then(result => {",Add error handler to arguments of .then()?,2016-11-30 19:54:09 +542,"@@ -5,330 +5,178 @@ + + 'use strict'; + +-import * as strings from 'vs/base/common/strings'; ++import uri from 'vs/base/common/uri'; + +-import * as fs from 'fs'; ++import * as os from 'os'; + import * as path from 'path'; + +-import * as baseMime from 'vs/base/common/mime'; +-import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; +-import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; ++import * as ipc from 'vs/base/parts/ipc/common/ipc'; ++ ++import { IProgress } from 'vs/platform/search/common/search'; + import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +-import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding'; + import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; ++import { ISearchWorkerConfig, ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc'; + +-interface ReadLinesOptions { +- bufferLength: number; +- encoding: string; +-} ++import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; + + export class Engine implements ISearchEngine { + + private static PROGRESS_FLUSH_CHUNK_SIZE = 50; // optimization: number of files to process before emitting progress event + +- private rootFolders: string[]; +- private extraFiles: string[]; +- private maxResults: number; ++ private config: IRawSearch; + private walker: FileWalker; +- private contentPattern: RegExp; +- private isCanceled: boolean; +- private isDone: boolean; +- private total: number; +- private worked: number; +- private progressed: number; + private walkerError: Error; +- private walkerIsDone: boolean; +- private fileEncoding: string; +- private limitReached: boolean; ++ ++ private isCanceled = false; ++ private isDone = false; ++ private totalBytes = 0; ++ private processedBytes = 0; ++ private progressed = 0; ++ private walkerIsDone = false; ++ private limitReached = false; ++ private numResults = 0; ++ ++ private nextWorker = 0; ++ private workers: ISearchWorker[] = []; ++ private workerClients: Client[] = []; + + constructor(config: IRawSearch, walker: FileWalker) { +- this.rootFolders = config.rootFolders; +- this.extraFiles = config.extraFiles; ++ this.config = config; + this.walker = walker; +- this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); +- this.isCanceled = false; +- this.limitReached = false; +- this.maxResults = config.maxResults; +- this.worked = 0; +- this.progressed = 0; +- this.total = 0; +- this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8; + } + +- public cancel(): void { ++ cancel(): void { + this.isCanceled = true; + this.walker.cancel(); +- } + +- public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { +- let resultCounter = 0; ++ this.workers.forEach(w => w.cancel()); ++ } + +- let progress = () => { +- this.progressed++; +- if (this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { +- onProgress({ total: this.total, worked: this.worked }); // buffer progress in chunks to reduce pressure ++ search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { ++ this.startWorkers(); ++ const progress = () => { ++ if (++this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { ++ onProgress({ total: this.totalBytes, worked: this.processedBytes }); // buffer progress in chunks to reduce pressure + } + }; + +- let unwind = (processed: number) => { +- this.worked += processed; ++ const unwind = (processed: number) => { ++ this.processedBytes += processed; + + // Emit progress() unless we got canceled or hit the limit + if (processed && !this.isDone && !this.isCanceled && !this.limitReached) { + progress(); + } + + // Emit done() +- if (this.worked === this.total && this.walkerIsDone && !this.isDone) { ++ if (!this.isDone && this.processedBytes === this.totalBytes && this.walkerIsDone) { + this.isDone = true; ++ this.disposeWorkers(); + done(this.walkerError, { + limitHit: this.limitReached, + stats: this.walker.getStats() + }); + } + }; + +- // Walk over the file system +- this.walker.walk(this.rootFolders, this.extraFiles, result => { +- const size = result.size || 1; +- this.total += size; +- +- // If the result is empty or we have reached the limit or we are canceled, ignore it +- if (this.limitReached || this.isCanceled) { +- return unwind(size); +- } ++ const run = (batch: string[], batchBytes: number): void => { ++ const worker = this.workers[this.nextWorker]; ++ this.nextWorker = (this.nextWorker + 1) % this.workers.length; + +- // Indicate progress to the outside +- progress(); +- +- let fileMatch: FileMatch = null; +- +- let doneCallback = (error?: Error) => { +- if (!error && !this.isCanceled && fileMatch && !fileMatch.isEmpty()) { +- onResult(fileMatch.serialize()); +- } +- +- return unwind(size); +- }; +- +- const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath; +- let perLineCallback = (line: string, lineNumber: number) => { +- if (this.limitReached || this.isCanceled) { +- return; // return early if canceled or limit reached ++ const maxResults = this.config.maxResults - this.numResults; ++ worker.search({ absolutePaths: batch, maxResults }).then(result => { ++ if (!result || this.limitReached || this.isCanceled) { ++ return unwind(batchBytes); + } + +- let lineMatch: LineMatch = null; +- let match = this.contentPattern.exec(line); +- +- // Record all matches into file result +- while (match !== null && match[0].length > 0 && !this.limitReached && !this.isCanceled) { +- resultCounter++; +- if (this.maxResults && resultCounter >= this.maxResults) { +- this.limitReached = true; +- } +- +- if (fileMatch === null) { +- fileMatch = new FileMatch(absolutePath); +- } +- +- if (lineMatch === null) { +- lineMatch = new LineMatch(line, lineNumber); +- fileMatch.addMatch(lineMatch); +- } +- +- lineMatch.addMatch(match.index, match[0].length); ++ const matches = result.matches; ++ this.numResults += result.numMatches; ++ matches.forEach(m => { ++ onResult(m); ++ }); + +- match = this.contentPattern.exec(line); ++ if (this.numResults >= this.config.maxResults) { ++ // It's possible to go over maxResults like this, but it's much simpler than trying to extract the exact number ++ // of file matches, line matches, and matches within a line to == maxResults. ++ this.limitReached = true; + } +- }; + +- // Read lines buffered to support large files +- this.readlinesAsync(absolutePath, perLineCallback, { bufferLength: 8096, encoding: this.fileEncoding }, doneCallback); +- }, (error, isLimitHit) => { +- this.walkerIsDone = true; +- this.walkerError = error; +- unwind(0 /* walker is done, indicate this back to our handler to be able to unwind */); +- }); +- } ++ unwind(batchBytes); ++ }); ++ }; + +- private readlinesAsync(filename: string, perLineCallback: (line: string, lineNumber: number) => void, options: ReadLinesOptions, callback: (error: Error) => void): void { +- fs.open(filename, 'r', null, (error: Error, fd: number) => { +- if (error) { +- return callback(error); ++ // Walk over the file system ++ let nextBatch = []; ++ let nextBatchBytes = 0; ++ const batchFlushBytes = 2 ** 20; // 1MB ++ this.walker.walk(this.config.rootFolders, this.config.extraFiles, result => { ++ let bytes = result.size || 1;",Any idea why we || 1? Would an empty file make the condition `this.processedBytes === this.totalBytes` further up never hold?,2016-11-30 19:34:35 +543,"@@ -5,330 +5,178 @@ + + 'use strict'; + +-import * as strings from 'vs/base/common/strings'; ++import uri from 'vs/base/common/uri'; + +-import * as fs from 'fs'; ++import * as os from 'os'; + import * as path from 'path'; + +-import * as baseMime from 'vs/base/common/mime'; +-import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; +-import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; ++import * as ipc from 'vs/base/parts/ipc/common/ipc'; ++ ++import { IProgress } from 'vs/platform/search/common/search'; + import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +-import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding'; + import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; ++import { ISearchWorkerConfig, ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc'; + +-interface ReadLinesOptions { +- bufferLength: number; +- encoding: string; +-} ++import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; + + export class Engine implements ISearchEngine { + + private static PROGRESS_FLUSH_CHUNK_SIZE = 50; // optimization: number of files to process before emitting progress event + +- private rootFolders: string[]; +- private extraFiles: string[]; +- private maxResults: number; ++ private config: IRawSearch; + private walker: FileWalker; +- private contentPattern: RegExp; +- private isCanceled: boolean; +- private isDone: boolean; +- private total: number; +- private worked: number; +- private progressed: number; + private walkerError: Error; +- private walkerIsDone: boolean; +- private fileEncoding: string; +- private limitReached: boolean; ++ ++ private isCanceled = false; ++ private isDone = false; ++ private totalBytes = 0; ++ private processedBytes = 0; ++ private progressed = 0; ++ private walkerIsDone = false; ++ private limitReached = false; ++ private numResults = 0; ++ ++ private nextWorker = 0; ++ private workers: ISearchWorker[] = []; ++ private workerClients: Client[] = []; + + constructor(config: IRawSearch, walker: FileWalker) { +- this.rootFolders = config.rootFolders; +- this.extraFiles = config.extraFiles; ++ this.config = config; + this.walker = walker; +- this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); +- this.isCanceled = false; +- this.limitReached = false; +- this.maxResults = config.maxResults; +- this.worked = 0; +- this.progressed = 0; +- this.total = 0; +- this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8; + } + +- public cancel(): void { ++ cancel(): void { + this.isCanceled = true; + this.walker.cancel(); +- } + +- public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { +- let resultCounter = 0; ++ this.workers.forEach(w => w.cancel()); ++ } + +- let progress = () => { +- this.progressed++; +- if (this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { +- onProgress({ total: this.total, worked: this.worked }); // buffer progress in chunks to reduce pressure ++ search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { ++ this.startWorkers(); ++ const progress = () => { ++ if (++this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { ++ onProgress({ total: this.totalBytes, worked: this.processedBytes }); // buffer progress in chunks to reduce pressure + } + }; + +- let unwind = (processed: number) => { +- this.worked += processed; ++ const unwind = (processed: number) => { ++ this.processedBytes += processed; + + // Emit progress() unless we got canceled or hit the limit + if (processed && !this.isDone && !this.isCanceled && !this.limitReached) { + progress(); + } + + // Emit done() +- if (this.worked === this.total && this.walkerIsDone && !this.isDone) { ++ if (!this.isDone && this.processedBytes === this.totalBytes && this.walkerIsDone) { + this.isDone = true; ++ this.disposeWorkers(); + done(this.walkerError, { + limitHit: this.limitReached, + stats: this.walker.getStats() + }); + } + }; + +- // Walk over the file system +- this.walker.walk(this.rootFolders, this.extraFiles, result => { +- const size = result.size || 1; +- this.total += size; +- +- // If the result is empty or we have reached the limit or we are canceled, ignore it +- if (this.limitReached || this.isCanceled) { +- return unwind(size); +- } ++ const run = (batch: string[], batchBytes: number): void => { ++ const worker = this.workers[this.nextWorker]; ++ this.nextWorker = (this.nextWorker + 1) % this.workers.length; + +- // Indicate progress to the outside +- progress(); +- +- let fileMatch: FileMatch = null; +- +- let doneCallback = (error?: Error) => { +- if (!error && !this.isCanceled && fileMatch && !fileMatch.isEmpty()) { +- onResult(fileMatch.serialize()); +- } +- +- return unwind(size); +- }; +- +- const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath; +- let perLineCallback = (line: string, lineNumber: number) => { +- if (this.limitReached || this.isCanceled) { +- return; // return early if canceled or limit reached ++ const maxResults = this.config.maxResults - this.numResults; ++ worker.search({ absolutePaths: batch, maxResults }).then(result => { ++ if (!result || this.limitReached || this.isCanceled) { ++ return unwind(batchBytes); + } + +- let lineMatch: LineMatch = null; +- let match = this.contentPattern.exec(line); +- +- // Record all matches into file result +- while (match !== null && match[0].length > 0 && !this.limitReached && !this.isCanceled) { +- resultCounter++; +- if (this.maxResults && resultCounter >= this.maxResults) { +- this.limitReached = true; +- } +- +- if (fileMatch === null) { +- fileMatch = new FileMatch(absolutePath); +- } +- +- if (lineMatch === null) { +- lineMatch = new LineMatch(line, lineNumber); +- fileMatch.addMatch(lineMatch); +- } +- +- lineMatch.addMatch(match.index, match[0].length); ++ const matches = result.matches; ++ this.numResults += result.numMatches; ++ matches.forEach(m => { ++ onResult(m); ++ }); + +- match = this.contentPattern.exec(line); ++ if (this.numResults >= this.config.maxResults) { ++ // It's possible to go over maxResults like this, but it's much simpler than trying to extract the exact number ++ // of file matches, line matches, and matches within a line to == maxResults. ++ this.limitReached = true; + } +- }; + +- // Read lines buffered to support large files +- this.readlinesAsync(absolutePath, perLineCallback, { bufferLength: 8096, encoding: this.fileEncoding }, doneCallback); +- }, (error, isLimitHit) => { +- this.walkerIsDone = true; +- this.walkerError = error; +- unwind(0 /* walker is done, indicate this back to our handler to be able to unwind */); +- }); +- } ++ unwind(batchBytes); ++ }); ++ }; + +- private readlinesAsync(filename: string, perLineCallback: (line: string, lineNumber: number) => void, options: ReadLinesOptions, callback: (error: Error) => void): void { +- fs.open(filename, 'r', null, (error: Error, fd: number) => { +- if (error) { +- return callback(error); ++ // Walk over the file system ++ let nextBatch = []; ++ let nextBatchBytes = 0; ++ const batchFlushBytes = 2 ** 20; // 1MB ++ this.walker.walk(this.config.rootFolders, this.config.extraFiles, result => { ++ let bytes = result.size || 1; ++ this.totalBytes += bytes; ++ ++ // If we have reached the limit or we are canceled, ignore it ++ if (this.limitReached || this.isCanceled) { ++ return unwind(bytes); + } + +- let buffer = new Buffer(options.bufferLength); +- let pos: number; +- let i: number; +- let line = ''; +- let lineNumber = 0; +- let lastBufferHadTraillingCR = false; +- +- const outer = this; +- +- function decodeBuffer(buffer: NodeBuffer, start: number, end: number): string { +- if (options.encoding === UTF8 || options.encoding === UTF8_with_bom) { +- return buffer.toString(undefined, start, end); // much faster to use built in toString() when encoding is default +- } ++ // Indicate progress to the outside ++ progress(); + +- return decode(buffer.slice(start, end), options.encoding); +- } ++ const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath; ++ nextBatch.push(absolutePath); ++ nextBatchBytes += bytes; + +- function lineFinished(offset: number): void { +- line += decodeBuffer(buffer, pos, i + offset); +- perLineCallback(line, lineNumber); +- line = ''; +- lineNumber++; +- pos = i + offset; ++ if (nextBatchBytes >= batchFlushBytes) { ++ run(nextBatch, nextBatchBytes); ++ nextBatch = []; ++ nextBatchBytes = 0; + } +- +- function readFile(isFirstRead: boolean, clb: (error: Error) => void): void { +- if (outer.limitReached || outer.isCanceled) { +- return clb(null); // return early if canceled or limit reached ++ }, (error, isLimitHit) => { ++ // Send any remaining paths to a worker, or unwind if we're stopping ++ if (nextBatch.length) { ++ if (this.limitReached || this.isCanceled) { ++ unwind(nextBatchBytes); ++ } else { ++ run(nextBatch, nextBatchBytes); + } +- +- fs.read(fd, buffer, 0, buffer.length, null, (error: Error, bytesRead: number, buffer: NodeBuffer) => { +- if (error || bytesRead === 0 || outer.limitReached || outer.isCanceled) { +- return clb(error); // return early if canceled or limit reached or no more bytes to read +- } +- +- pos = 0; +- i = 0; +- +- // Detect encoding and mime when this is the beginning of the file +- if (isFirstRead) { +- let mimeAndEncoding = detectMimeAndEncodingFromBuffer(buffer, bytesRead); +- if (mimeAndEncoding.mimes[mimeAndEncoding.mimes.length - 1] !== baseMime.MIME_TEXT) { +- return clb(null); // skip files that seem binary +- } +- +- // Check for BOM offset +- switch (mimeAndEncoding.encoding) { +- case UTF8: +- pos = i = 3; +- options.encoding = UTF8; +- break; +- case UTF16be: +- pos = i = 2; +- options.encoding = UTF16be; +- break; +- case UTF16le: +- pos = i = 2; +- options.encoding = UTF16le; +- break; +- } +- } +- +- if (lastBufferHadTraillingCR) { +- if (buffer[i] === 0x0a) { // LF (Line Feed) +- lineFinished(1); +- i++; +- } else { +- lineFinished(0); +- } +- +- lastBufferHadTraillingCR = false; +- } +- +- for (; i < bytesRead; ++i) { +- if (buffer[i] === 0x0a) { // LF (Line Feed) +- lineFinished(1); +- } else if (buffer[i] === 0x0d) { // CR (Carriage Return) +- if (i + 1 === bytesRead) { +- lastBufferHadTraillingCR = true; +- } else if (buffer[i + 1] === 0x0a) { // LF (Line Feed) +- lineFinished(2); +- i++; +- } else { +- lineFinished(1); +- } +- } +- } +- +- line += decodeBuffer(buffer, pos, bytesRead); +- +- readFile(false /* isFirstRead */, clb); // Continue reading +- }); + } + +- readFile(true /* isFirstRead */, (error: Error) => { +- if (error) { +- return callback(error); +- } +- +- if (line.length) { +- perLineCallback(line, lineNumber); // handle last line +- } +- +- fs.close(fd, (error: Error) => { +- callback(error); +- }); +- }); ++ this.walkerIsDone = true; ++ this.walkerError = error; + }); + } +-} +- +-class FileMatch implements ISerializedFileMatch { +- public path: string; +- public lineMatches: LineMatch[]; +- +- constructor(path: string) { +- this.path = path; +- this.lineMatches = []; +- } + +- public addMatch(lineMatch: LineMatch): void { +- this.lineMatches.push(lineMatch); +- } +- +- public isEmpty(): boolean { +- return this.lineMatches.length === 0; +- } +- +- public serialize(): ISerializedFileMatch { +- let lineMatches: ILineMatch[] = []; +- +- for (let i = 0; i < this.lineMatches.length; i++) { +- lineMatches.push(this.lineMatches[i].serialize()); ++ private startWorkers(): void { ++ // If the CPU has hyperthreading enabled, this will report (# of physical cores)*2. ++ const numWorkers = os.cpus().length; ++ for (let i = 0; i < numWorkers; i++) { ++ this.createWorker(i); + } +- +- return { +- path: this.path, +- lineMatches: lineMatches +- }; +- } +-} +- +-class LineMatch implements ILineMatch { +- public preview: string; +- public lineNumber: number; +- public offsetAndLengths: number[][]; +- +- constructor(preview: string, lineNumber: number) { +- this.preview = preview.replace(/(\r|\n)*$/, ''); +- this.lineNumber = lineNumber; +- this.offsetAndLengths = []; + } + +- public getText(): string { +- return this.preview; +- } ++ private createWorker(id: number): void { ++ let client = new Client( ++ uri.parse(require.toUrl('bootstrap')).fsPath, ++ { ++ serverName: 'Search Worker ' + id, ++ args: ['--type=searchWorker'], ++ env: { ++ AMD_ENTRYPOINT: 'vs/workbench/services/search/node/worker/searchWorkerApp', ++ PIPE_LOGGING: 'true', ++ VERBOSE_LOGGING: 'true'","Others seem to be using `environmentService.verbose` or `!environmentService.isBuilt || environmentService.verbose`. Not sure if it matters in this case, but we should avoid being noisy.",2016-11-30 19:47:23 +547,"@@ -5,330 +5,178 @@ + + 'use strict'; + +-import * as strings from 'vs/base/common/strings'; ++import uri from 'vs/base/common/uri'; + +-import * as fs from 'fs'; ++import * as os from 'os'; + import * as path from 'path'; + +-import * as baseMime from 'vs/base/common/mime'; +-import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; +-import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime'; ++import * as ipc from 'vs/base/parts/ipc/common/ipc'; ++ ++import { IProgress } from 'vs/platform/search/common/search'; + import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; +-import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding'; + import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; ++import { ISearchWorkerConfig, ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc'; + +-interface ReadLinesOptions { +- bufferLength: number; +- encoding: string; +-} ++import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; + + export class Engine implements ISearchEngine { + + private static PROGRESS_FLUSH_CHUNK_SIZE = 50; // optimization: number of files to process before emitting progress event + +- private rootFolders: string[]; +- private extraFiles: string[]; +- private maxResults: number; ++ private config: IRawSearch; + private walker: FileWalker; +- private contentPattern: RegExp; +- private isCanceled: boolean; +- private isDone: boolean; +- private total: number; +- private worked: number; +- private progressed: number; + private walkerError: Error; +- private walkerIsDone: boolean; +- private fileEncoding: string; +- private limitReached: boolean; ++ ++ private isCanceled = false; ++ private isDone = false; ++ private totalBytes = 0; ++ private processedBytes = 0; ++ private progressed = 0; ++ private walkerIsDone = false; ++ private limitReached = false; ++ private numResults = 0; ++ ++ private nextWorker = 0; ++ private workers: ISearchWorker[] = []; ++ private workerClients: Client[] = []; + + constructor(config: IRawSearch, walker: FileWalker) { +- this.rootFolders = config.rootFolders; +- this.extraFiles = config.extraFiles; ++ this.config = config; + this.walker = walker; +- this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); +- this.isCanceled = false; +- this.limitReached = false; +- this.maxResults = config.maxResults; +- this.worked = 0; +- this.progressed = 0; +- this.total = 0; +- this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8; + } + +- public cancel(): void { ++ cancel(): void { + this.isCanceled = true; + this.walker.cancel(); +- } + +- public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { +- let resultCounter = 0; ++ this.workers.forEach(w => w.cancel()); ++ } + +- let progress = () => { +- this.progressed++; +- if (this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { +- onProgress({ total: this.total, worked: this.worked }); // buffer progress in chunks to reduce pressure ++ search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { ++ this.startWorkers(); ++ const progress = () => { ++ if (++this.progressed % Engine.PROGRESS_FLUSH_CHUNK_SIZE === 0) { ++ onProgress({ total: this.totalBytes, worked: this.processedBytes }); // buffer progress in chunks to reduce pressure + } + }; + +- let unwind = (processed: number) => { +- this.worked += processed; ++ const unwind = (processed: number) => { ++ this.processedBytes += processed; + + // Emit progress() unless we got canceled or hit the limit + if (processed && !this.isDone && !this.isCanceled && !this.limitReached) { + progress(); + } + + // Emit done() +- if (this.worked === this.total && this.walkerIsDone && !this.isDone) { ++ if (!this.isDone && this.processedBytes === this.totalBytes && this.walkerIsDone) { + this.isDone = true; ++ this.disposeWorkers(); + done(this.walkerError, { + limitHit: this.limitReached, + stats: this.walker.getStats() + }); + } + }; + +- // Walk over the file system +- this.walker.walk(this.rootFolders, this.extraFiles, result => { +- const size = result.size || 1; +- this.total += size; +- +- // If the result is empty or we have reached the limit or we are canceled, ignore it +- if (this.limitReached || this.isCanceled) { +- return unwind(size); +- } ++ const run = (batch: string[], batchBytes: number): void => { ++ const worker = this.workers[this.nextWorker]; ++ this.nextWorker = (this.nextWorker + 1) % this.workers.length; + +- // Indicate progress to the outside +- progress(); +- +- let fileMatch: FileMatch = null; +- +- let doneCallback = (error?: Error) => { +- if (!error && !this.isCanceled && fileMatch && !fileMatch.isEmpty()) { +- onResult(fileMatch.serialize()); +- } +- +- return unwind(size); +- }; +- +- const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath; +- let perLineCallback = (line: string, lineNumber: number) => { +- if (this.limitReached || this.isCanceled) { +- return; // return early if canceled or limit reached ++ const maxResults = this.config.maxResults - this.numResults; ++ worker.search({ absolutePaths: batch, maxResults }).then(result => { ++ if (!result || this.limitReached || this.isCanceled) { ++ return unwind(batchBytes); + } + +- let lineMatch: LineMatch = null; +- let match = this.contentPattern.exec(line); +- +- // Record all matches into file result +- while (match !== null && match[0].length > 0 && !this.limitReached && !this.isCanceled) { +- resultCounter++; +- if (this.maxResults && resultCounter >= this.maxResults) { +- this.limitReached = true; +- } +- +- if (fileMatch === null) { +- fileMatch = new FileMatch(absolutePath); +- } +- +- if (lineMatch === null) { +- lineMatch = new LineMatch(line, lineNumber); +- fileMatch.addMatch(lineMatch); +- } +- +- lineMatch.addMatch(match.index, match[0].length); ++ const matches = result.matches; ++ this.numResults += result.numMatches; ++ matches.forEach(m => { ++ onResult(m); ++ }); + +- match = this.contentPattern.exec(line); ++ if (this.numResults >= this.config.maxResults) { ++ // It's possible to go over maxResults like this, but it's much simpler than trying to extract the exact number ++ // of file matches, line matches, and matches within a line to == maxResults. ++ this.limitReached = true; + } +- }; + +- // Read lines buffered to support large files +- this.readlinesAsync(absolutePath, perLineCallback, { bufferLength: 8096, encoding: this.fileEncoding }, doneCallback); +- }, (error, isLimitHit) => { +- this.walkerIsDone = true; +- this.walkerError = error; +- unwind(0 /* walker is done, indicate this back to our handler to be able to unwind */); +- }); +- } ++ unwind(batchBytes); ++ }); ++ }; + +- private readlinesAsync(filename: string, perLineCallback: (line: string, lineNumber: number) => void, options: ReadLinesOptions, callback: (error: Error) => void): void { +- fs.open(filename, 'r', null, (error: Error, fd: number) => { +- if (error) { +- return callback(error); ++ // Walk over the file system ++ let nextBatch = []; ++ let nextBatchBytes = 0; ++ const batchFlushBytes = 2 ** 20; // 1MB ++ this.walker.walk(this.config.rootFolders, this.config.extraFiles, result => { ++ let bytes = result.size || 1; ++ this.totalBytes += bytes; ++ ++ // If we have reached the limit or we are canceled, ignore it ++ if (this.limitReached || this.isCanceled) { ++ return unwind(bytes); + } + +- let buffer = new Buffer(options.bufferLength); +- let pos: number; +- let i: number; +- let line = ''; +- let lineNumber = 0; +- let lastBufferHadTraillingCR = false; +- +- const outer = this; +- +- function decodeBuffer(buffer: NodeBuffer, start: number, end: number): string { +- if (options.encoding === UTF8 || options.encoding === UTF8_with_bom) { +- return buffer.toString(undefined, start, end); // much faster to use built in toString() when encoding is default +- } ++ // Indicate progress to the outside ++ progress(); + +- return decode(buffer.slice(start, end), options.encoding); +- } ++ const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath; ++ nextBatch.push(absolutePath); ++ nextBatchBytes += bytes; + +- function lineFinished(offset: number): void { +- line += decodeBuffer(buffer, pos, i + offset); +- perLineCallback(line, lineNumber); +- line = ''; +- lineNumber++; +- pos = i + offset; ++ if (nextBatchBytes >= batchFlushBytes) { ++ run(nextBatch, nextBatchBytes); ++ nextBatch = []; ++ nextBatchBytes = 0; + } +- +- function readFile(isFirstRead: boolean, clb: (error: Error) => void): void { +- if (outer.limitReached || outer.isCanceled) { +- return clb(null); // return early if canceled or limit reached ++ }, (error, isLimitHit) => { ++ // Send any remaining paths to a worker, or unwind if we're stopping ++ if (nextBatch.length) { ++ if (this.limitReached || this.isCanceled) { ++ unwind(nextBatchBytes); ++ } else { ++ run(nextBatch, nextBatchBytes); + } +- +- fs.read(fd, buffer, 0, buffer.length, null, (error: Error, bytesRead: number, buffer: NodeBuffer) => { +- if (error || bytesRead === 0 || outer.limitReached || outer.isCanceled) { +- return clb(error); // return early if canceled or limit reached or no more bytes to read +- } +- +- pos = 0; +- i = 0; +- +- // Detect encoding and mime when this is the beginning of the file +- if (isFirstRead) { +- let mimeAndEncoding = detectMimeAndEncodingFromBuffer(buffer, bytesRead); +- if (mimeAndEncoding.mimes[mimeAndEncoding.mimes.length - 1] !== baseMime.MIME_TEXT) { +- return clb(null); // skip files that seem binary +- } +- +- // Check for BOM offset +- switch (mimeAndEncoding.encoding) { +- case UTF8: +- pos = i = 3; +- options.encoding = UTF8; +- break; +- case UTF16be: +- pos = i = 2; +- options.encoding = UTF16be; +- break; +- case UTF16le: +- pos = i = 2; +- options.encoding = UTF16le; +- break; +- } +- } +- +- if (lastBufferHadTraillingCR) { +- if (buffer[i] === 0x0a) { // LF (Line Feed) +- lineFinished(1); +- i++; +- } else { +- lineFinished(0); +- } +- +- lastBufferHadTraillingCR = false; +- } +- +- for (; i < bytesRead; ++i) { +- if (buffer[i] === 0x0a) { // LF (Line Feed) +- lineFinished(1); +- } else if (buffer[i] === 0x0d) { // CR (Carriage Return) +- if (i + 1 === bytesRead) { +- lastBufferHadTraillingCR = true; +- } else if (buffer[i + 1] === 0x0a) { // LF (Line Feed) +- lineFinished(2); +- i++; +- } else { +- lineFinished(1); +- } +- } +- } +- +- line += decodeBuffer(buffer, pos, bytesRead); +- +- readFile(false /* isFirstRead */, clb); // Continue reading +- }); + } + +- readFile(true /* isFirstRead */, (error: Error) => { +- if (error) { +- return callback(error); +- } +- +- if (line.length) { +- perLineCallback(line, lineNumber); // handle last line +- } +- +- fs.close(fd, (error: Error) => { +- callback(error); +- }); +- }); ++ this.walkerIsDone = true; ++ this.walkerError = error; + }); + } +-} +- +-class FileMatch implements ISerializedFileMatch { +- public path: string; +- public lineMatches: LineMatch[]; +- +- constructor(path: string) { +- this.path = path; +- this.lineMatches = []; +- } + +- public addMatch(lineMatch: LineMatch): void { +- this.lineMatches.push(lineMatch); +- } +- +- public isEmpty(): boolean { +- return this.lineMatches.length === 0; +- } +- +- public serialize(): ISerializedFileMatch { +- let lineMatches: ILineMatch[] = []; +- +- for (let i = 0; i < this.lineMatches.length; i++) { +- lineMatches.push(this.lineMatches[i].serialize()); ++ private startWorkers(): void { ++ // If the CPU has hyperthreading enabled, this will report (# of physical cores)*2. ++ const numWorkers = os.cpus().length; ++ for (let i = 0; i < numWorkers; i++) { ++ this.createWorker(i); + } +- +- return { +- path: this.path, +- lineMatches: lineMatches +- }; +- } +-} +- +-class LineMatch implements ILineMatch { +- public preview: string; +- public lineNumber: number; +- public offsetAndLengths: number[][]; +- +- constructor(preview: string, lineNumber: number) { +- this.preview = preview.replace(/(\r|\n)*$/, ''); +- this.lineNumber = lineNumber; +- this.offsetAndLengths = []; + } + +- public getText(): string { +- return this.preview; +- } ++ private createWorker(id: number): void { ++ let client = new Client( ++ uri.parse(require.toUrl('bootstrap')).fsPath, ++ { ++ serverName: 'Search Worker ' + id, ++ args: ['--type=searchWorker'], ++ env: { ++ AMD_ENTRYPOINT: 'vs/workbench/services/search/node/worker/searchWorkerApp', ++ PIPE_LOGGING: 'true', ++ VERBOSE_LOGGING: 'true' ++ } ++ }); + +- public getLineNumber(): number { +- return this.lineNumber; +- } ++ // Make async? ++ const channel = ipc.getNextTickChannel(client.getChannel('searchWorker')); ++ const channelClient = new SearchWorkerChannelClient(channel); ++ const config: ISearchWorkerConfig = { pattern: this.config.contentPattern, id, fileEncoding: this.config.fileEncoding }; ++ channelClient.initialize(config);",Add error handler.,2016-11-30 19:56:21 +91,"@@ -5,4 +5,9 @@ + + import {IComposite} from 'vs/workbench/common/composite'; + +-export interface IViewlet extends IComposite { } ++export interface IViewlet extends IComposite { ++ /** ++ * Returns the minimal width needed to avoid any content horizontal truncation ++ */ ++ getOptimalWidth?(): number;","Suggest to make this a non optional method and implement it by default in the base viewlet class. +",2016-03-30 05:25:08 +290,"@@ -50,8 +50,8 @@ export function create(container: Builder, keybindingService: IKeybindingService + entry.ids + .map(id => keybindingService.lookupKeybindings(id) + .map(k => keybindingService.getLabelFor(k)) +- .join(', ') || UNBOUND) +- .join(' / ') ++ .join(' or ') || UNBOUND) ++ .join(' or ')","We'll need to translate these. +",2016-09-27 04:34:16 +563,"@@ -51,11 +51,6 @@ export class BackupMainService implements IBackupMainService { + } + + public registerWindowForBackups(windowId: number, isEmptyWorkspace: boolean, backupFolder?: string, workspacePath?: string): void {","@Tyriar I didnt know you had this check in here, I am also fine leaving it there to keep this knowledge inside the service!",2016-12-02 08:28:50 +497,"@@ -51,6 +51,7 @@ export interface IEnvironmentService { + appSettingsPath: string; + appKeybindingsPath: string; + ++ isBackupEnabled: boolean;","@Tyriar not so sure about introducing such a specific option to the environment service. keep in mind that it is being used in a lot of environments, including the CLI when managing extensions. I think a better approach is to introduce an `isExtensionDevelopment` flag that we can use to replace all our checks for `extensionDevelopmentPath` throughout the code. +",2016-11-17 05:58:36 +10,"@@ -51,7 +51,7 @@ export var language = { + 'internal', 'private', 'abstract', 'sealed', 'static', 'struct', 'readonly', + 'volatile', 'virtual', 'override', 'params', 'get', 'set', 'add', 'remove', + 'operator', 'true', 'false', 'implicit', 'explicit', 'interface', 'enum', +- 'null', 'async', 'await' ++ 'null', 'async', 'await','fixed','sizeof','stackalloc','unsafe' + ],","This change is good, but note that this file is not in use in VS Code. For CSharp colorization in VS Code we use `/extensions/csharp/syntaxes/csharp.json`. +This file is used for the standalone editor build. +",2015-11-21 19:13:06 +683,"@@ -510,30 +505,6 @@ export class RawDebugSession extends v8.V8Protocol implements debug.ISession { + return ret; + } + ",Great that this is no longer in RawDebugSession!,2017-01-18 14:03:24 +854,"@@ -511,7 +511,8 @@ export class VSCodeMenu { + + if (folders.length || files.length) { + openRecentMenu.append(__separator__()); +- openRecentMenu.append(new MenuItem(this.likeAction('clearRecentlyOpened', { label: mnemonicLabel(nls.localize({ key: 'miClearItems', comment: ['&& denotes a mnemonic'] }, ""&&Clear Items"")), click: () => this.windowsService.clearRecentPathsList() }, false))); ++ //workbench.action.clearRecentItems",Extra comment?,2017-03-23 14:05:35 +110,"@@ -52,24 +54,40 @@ export interface IWorkbenchActionRegistry { + * Returns the category for the given action or null iff none. + */ + getCategory(actionId: string): string; ++ ++ /** ++ * Returns the keywords associated with the given action or null iff none. ++ */ ++ getKeywords(actionId: string): string[]; + } + + class WorkbenchActionRegistry implements IWorkbenchActionRegistry { + private workbenchActions: collections.IStringDictionary; + private mapActionIdToCategory: { [id: string]: string; }; ++ private mapActionIdToKeywords: { [id: string]: string[]; }; + + constructor() { + this.workbenchActions = Object.create(null); + this.mapActionIdToCategory = Object.create(null); ++ this.mapActionIdToKeywords = Object.create(null);","will it be better to actually have a map to everything? Have map where values will be some structure, so you will not need to maintain two of them? +",2016-04-18 13:35:24 +109,"@@ -52,24 +54,40 @@ export interface IWorkbenchActionRegistry { + * Returns the category for the given action or null iff none. + */ + getCategory(actionId: string): string; ++ ++ /** ++ * Returns the keywords associated with the given action or null iff none. ++ */ ++ getKeywords(actionId: string): string[]; + } + + class WorkbenchActionRegistry implements IWorkbenchActionRegistry { + private workbenchActions: collections.IStringDictionary; + private mapActionIdToCategory: { [id: string]: string; }; ++ private mapActionIdToKeywords: { [id: string]: string[]; }; + + constructor() { + this.workbenchActions = Object.create(null); + this.mapActionIdToCategory = Object.create(null); ++ this.mapActionIdToKeywords = Object.create(null); + } + +- public registerWorkbenchAction(descriptor: SyncActionDescriptor, category?: string): void { ++ public registerWorkbenchAction(descriptor: SyncActionDescriptor, category?: string): void; ++ public registerWorkbenchAction(descriptor: SyncActionDescriptor, keywords?: string[]): void; ++ public registerWorkbenchAction(descriptor: SyncActionDescriptor, category?: string, keywords?: string[]): void; ++ public registerWorkbenchAction(descriptor: SyncActionDescriptor, categoryOrKeywords?: string|string[], keywords?: string[]): void { + if (!this.workbenchActions[descriptor.id]) { + this.workbenchActions[descriptor.id] = descriptor; + registerWorkbenchCommandFromAction(descriptor); + +- if (category) { +- this.mapActionIdToCategory[descriptor.id] = category; ++ if (typeof categoryOrKeywords === 'string') {","`Types.isString`? +",2016-04-18 13:34:07 +193,"@@ -52,7 +55,7 @@ export class TerminalInstance { + this.isExiting = true; + this.dispose(); + if (exitCode) { +- console.error('Integrated terminal exited with code ' + exitCode); ++ this.messageService.show(Severity.Error, nls.localize('terminal.integrated.exitedWithCode', 'Terminal: The terminal process terminated with exit code: {0}', exitCode));","I don't think `Terminal:` is necessary here, doesn't seem to be used elsewhere (from a cursory search of `Severity.Error`). +",2016-07-05 20:53:09 +156,"@@ -53,6 +53,11 @@ export class SassParser extends cssParser.Parser { + + // Sass variables: $font-size: 12px; + public _parseVariableDeclaration(panic:scanner.TokenType[]=[]): nodes.VariableDeclaration { ++ var cssVariableDeclaration= super._parseCssVariableDeclaration(panic);","That looks wrong. Not all places where you can declare a sass variable are also suited to declare a css variable. +",2016-05-20 10:23:37 +304,"@@ -532,7 +532,7 @@ export class TextEditorOptions extends EditorOptions { + public static from(input: IResourceInput): TextEditorOptions { + let options: TextEditorOptions = null; + if (input && input.options) { +- if (input.options.selection || input.options.forceOpen || input.options.revealIfVisible || input.options.preserveFocus || input.options.pinned || input.options.inactive || typeof input.options.index === 'number') { ++ if (input.options.selection || input.options.forceOpen || input.options.revealIfVisible || !input.options.preserveFocus || input.options.pinned || input.options.inactive || typeof input.options.index === 'number') {","all of this cannot be changed... +",2016-10-05 08:24:48 +631,"@@ -536,25 +540,37 @@ + + + +- (^|\G)(?!\s*$|#|[ ]{0,3}((([*_][ ]{0,2}\2){2,}[ \t]*$\n?)|([*+-]([ ]{1,3}|\t)))|\s*\[.+?\]:|>) +- +- raw_block +- +- begin +- (^|\G)([ ]{4}|\t) +- name +- markup.raw.block.markdown +- while +- (^|\G)([ ]{4}|\t) ++ (^|\G)(?!\s*$|#|[`~]{0,3}|[ ]{0,3}((([*_][ ]{0,2}\2){2,}[ \t]*$\n?)|([*+-]([ ]{1,3}|\t)))|\s*\[.+?\]:|>) + + fenced_code_block_css + + begin +- (^|\G)\s*(([`~]){3,})\s*(css|css.erb)(\s+.*)?$ ++ (^|\G)\s*([`~]{3,})\s*(css|css.erb)\n + name + markup.fenced_code.block.markdown +- while +- (^|\G)(?!\s*\2\3*\s*$) ++ end ++ (^|\G)\s*([`~]{3,})\n",We have to use a while clause here. This prevents broken language grammars from leaking outside of the fenced block. Switching to while from end fixed a large number of syntax highlighting issues.,2016-12-20 23:29:21 +848,"@@ -539,6 +539,48 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal + return this.panelMaximized; + } + ++ // Add reset for keyboard support ++ public resetSideBarWidth(): number {",Not being used?,2017-03-22 13:26:51 +849,"@@ -539,6 +539,48 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal + return this.panelMaximized; + } + ++ // Add reset for keyboard support ++ public resetSideBarWidth(): number { ++ this.sidebarWidth = MIN_SIDEBAR_PART_WIDTH; ++ return this.sidebarWidth; ++ } ++ ++ // change part size along the main axis ++ public setPartSizeChange(part: Parts, sizeChange: number): boolean {",This method should do the same validation about minimal and maximal sizes for a specific part as we already do when the user resizes a view using the sashes (e.g. [here](https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/browser/layout.ts#L192)),2017-03-22 13:28:25 +369,"@@ -549,6 +568,33 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe + return promiseCompletedOnHide; + } + ++ private handleOnCancel(isPicker: boolean): void { ++ // restore the editor part state after cancelling ++ this.historyService.block(true);","@wprater shouldn't this be `block(false)`? also I am missing the all to `block(true)`. +",2016-10-21 10:03:37 +370,"@@ -549,6 +568,33 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe + return promiseCompletedOnHide; + } + ++ private handleOnCancel(isPicker: boolean): void { ++ // restore the editor part state after cancelling ++ this.historyService.block(true); ++ ++ // restore the previous preview editor ++ if (this.previousPreviewEditorInput) {","@wprater unfortunately I think this is more complicated for the restore part. I can see the following states: +- 1.) no active editor +- 2.) no preview editor +- 3.) active editor is preview editor +- 4.) active editor is not preview editor + +1.) easy, just close the preview editor that was opened +2.) also easy, just close the preview editor +3.) restore the previous active editor by opening it +4.) restore the previous editor in the preview slot but open it in the background because it was not the active one. also open the previous active editor + +Also you have to be careful that you do this from the `onCancel()` callback. Because as far as I remember this method is not called when you actually pick an entry from quick open. I would expect some additional logic when an element is picked. +",2016-10-21 10:06:44 +67,"@@ -55,23 +55,30 @@ export interface IThread extends ITreeElement { + threadId: number; + name: string; + stoppedDetails: IRawStoppedDetails; ++ ++ /** ++ * Queries the debug adapter for the callstack and returns a promise with ++ * the stack frames of the callstack. ++ * If the thread is not stopped, it returns a promise to an empty array. ++ */ + getCallStack(debugService: IDebugService): TPromise; +- clearCallStack(): void; + + /** +- * Indicates whether the call stack for this thread can be obtained from +- * the debug adapter. ++ * Gets the callstack if it has already been received from the debug ++ * adapter, otherwise it returns undefined. + */ +- callStackObtainable: boolean; ++ getCachedCallStack(): IStackFrame[]; + + /** +- * Indicates whether the call stack for this thread is available because it +- * has already been obtained from the debug adapter. +- * This property is used to determine whether the call stack is available +- * without triggering a call to the debug adapter. ++ * Invalidates the callstack cache + */ +- callStackAvailable: boolean; ++ clearCallStack(): void; + ++ /** ++ * Indicates whether this thread is stopped. The callstack for stopped ++ * threads can be retrieved from the debug adapter. ++ */ ++ stopped: boolean;","`stopped` doesn't necessarily need to be exposed. We could have two methods `setRunning` and `setStopped` that would set `stopped` to false and `true`, respectively. + +I left it exposed so that the tests can check it. I'm fine removing `stopped` from the interface and only have setters. Let me know what you think. +",2016-03-16 02:48:04 +881,"@@ -55,7 +55,39 @@ export class CodeSnippet implements ICodeSnippet { + } + + static fromEmmet(template: string): CodeSnippet { +- return EmmetSnippetParser.parse(template); ++ //return EmmetSnippetParser.parse(template); ++ ++ let matchFinalStops = template.match(/\$\{0\}/g); ++ if (!matchFinalStops || matchFinalStops.length === 1) { ++ return CodeSnippet.fromTextmate(template); ++ } ++ ++ // Emmet sometimes returns snippets with multiple ${0} ++ // In such cases, replace ${0} with incremental tab stops ++","There is also the shorthand notion which omits the curlies, like so `foo$1ba$0r`. Isn't emmet using that?",2017-04-14 07:41:24 +882,"@@ -55,7 +55,39 @@ export class CodeSnippet implements ICodeSnippet { + } + + static fromEmmet(template: string): CodeSnippet { +- return EmmetSnippetParser.parse(template); ++ //return EmmetSnippetParser.parse(template); ++ ++ let matchFinalStops = template.match(/\$\{0\}/g); ++ if (!matchFinalStops || matchFinalStops.length === 1) { ++ return CodeSnippet.fromTextmate(template); ++ } ++ ++ // Emmet sometimes returns snippets with multiple ${0} ++ // In such cases, replace ${0} with incremental tab stops ++ ++ let maxTabStop = -1; ++ let matches = []; ++ let regex = /\$\{(\d+)\}/g; ++ while (matches = regex.exec(template)) { ++ let tabStop = Number(matches[1]); ++ if (tabStop > maxTabStop) { ++ maxTabStop = tabStop; ++ } ++ } ++ regex = /\$\{(\d+):[^\}]+\}/g; ++ matches = []; ++ while (matches = regex.exec(template)) { ++ let tabStop = Number(matches[1]); ++ if (tabStop > maxTabStop) { ++ maxTabStop = tabStop; ++ } ++ }","If this is becoming too complex, e.g `$1`, with escaped `}`, or nested placeholder (stretch, like `foo ${1:\}}` or `foo${2:b${1:ar}$0`), we should consider using the (new) snippet parser (`SnippetParser`) which allows you read all placeholders. Tho I'd say that depends on the Emmet-TextMate-subset",2017-04-14 07:44:44 +291,"@@ -55,7 +55,8 @@ + width: 49%; + margin: 0 1% 0 0; + text-align: right; +- font-weight: bold; ++ font-weight: normal;","You can just take out `font-weight` altogether +",2016-09-29 00:14:11 +902,"@@ -55,8 +55,26 @@ export class ExtHostEditors extends ExtHostEditorsShape { + return this._extHostDocumentsAndEditors.allEditors(); + } + +- showTextDocument(document: vscode.TextDocument, column: vscode.ViewColumn, preserveFocus: boolean): TPromise { +- return this._proxy.$tryShowTextDocument(document.uri, TypeConverters.fromViewColumn(column), preserveFocus).then(id => { ++ showTextDocument(document: vscode.TextDocument, column: vscode.ViewColumn, preserveFocus: boolean): TPromise; ++ showTextDocument(document: vscode.TextDocument, options: { column: vscode.ViewColumn, preserveFocus: boolean, pinned: boolean }): TPromise; ++ showTextDocument(document: vscode.TextDocument, columnOrOptions: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise; ++ showTextDocument(document: vscode.TextDocument, columnOrOptions: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise { ++ let options: ITextDocumentShowOptions; ++ if (typeof columnOrOptions === 'number') { ++ options = { ++ position: TypeConverters.fromViewColumn(columnOrOptions), ++ preserveFocus: preserveFocus, ++ pinned: true ++ }; ++ } else { ++ options = {",The `else` cannot be unconditional because it will be hit when no second parameter is given. Add a check like `typeof columnOrOptions === 'object'`,2017-04-25 14:05:50 +224,"@@ -553,6 +552,18 @@ export class OneCursor { + public getViewLineMaxColumn(lineNumber:number): number { + return this.viewModelHelper.viewModel.getLineMaxColumn(lineNumber); + } ++ public getViewLineMinColumn(lineNumber:number): number { ++ return this.viewModelHelper.viewModel.getLineMinColumn(lineNumber); ++ } ++ public getViewLineCenterColumn(lineNumber:number): number {","You have to be careful about this one. This does not work for lines containing bi-di or variable width character sizes. +",2016-07-15 11:12:25 +13,"@@ -553,6 +564,9 @@ export class MainThreadDocuments { + modelService.onModelRemoved.add(this._onModelRemoved, this, this._toDispose); + modelService.onModelModeChanged.add(this._onModelModeChanged, this, this._toDispose); + ++ this._toDispose.push(eventService.addListener2(FileEventType.FILE_SAVING, (e: LocalFileChangeEvent) => { ++ this._proxy._acceptModelSaving(e.getAfter().resource); ++ }));","What guarantees do we make when a document is being saved? Can people still modify etc? +",2015-11-24 09:12:06 +864,"@@ -555,13 +556,15 @@ export class GlobalNewUntitledFileAction extends Action { + id: string, + label: string, + @IWorkbenchEditorService private editorService: IWorkbenchEditorService, +- @IUntitledEditorService private untitledEditorService: IUntitledEditorService ++ @IUntitledEditorService private untitledEditorService: IUntitledEditorService, ++ @IConfigurationService private configurationService: IConfigurationService + ) { + super(id, label); + } + + public run(): TPromise { +- const input = this.untitledEditorService.createOrGet(); ++ const configuration = this.configurationService.getConfiguration();","I suggest to not add this to the action but actually to the place where untitled editors are being created. There can be other ways how untitled buffers open (e.g. from extensions) and I think a configured default language would also apply there. + +I am thinking somewhere inside https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/services/untitled/common/untitledEditorService.ts#L177 to use the configuration if the `modeId` parameter is undefined.",2017-03-25 23:52:49 +743,"@@ -557,6 +617,7 @@ class MouseDownState { + private _lastMouseDownPositionEqualCount: number; + private _lastMouseDownCount: number; + private _lastSetMouseDownCountTime: number; ++ private _lastMouseDownEvent: 'mouseDown' | 'drag';",pick a better name for this. Perhaps just a boolean `isDragAndDrop` would do. This boolean should be set only in the `start` method above,2017-02-20 11:13:52 +732,"@@ -558,4 +560,97 @@ export class ViewModel extends EventEmitter implements IViewModel { + public validateModelPosition(position: editorCommon.IPosition): Position { + return this.model.validatePosition(position); + } ++ ++ public getPlainTextToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string { ++ let newLineCharacter = this.getEOL(); ++ ++ if (ranges.length === 1) { ++ let range: Range = ranges[0]; ++ if (range.isEmpty()) { ++ if (enableEmptySelectionClipboard) { ++ let modelLineNumber = this.coordinatesConverter.convertViewPositionToModelPosition(new Position(range.startLineNumber, 1)).lineNumber; ++ return this.getModelLineContent(modelLineNumber) + newLineCharacter; ++ } else { ++ return ''; ++ } ++ } ++ ++ return this.getValueInRange(range, editorCommon.EndOfLinePreference.TextDefined); ++ } else { ++ ranges = ranges.slice(0).sort(Range.compareRangesUsingStarts); ++ let result: string[] = []; ++ for (let i = 0; i < ranges.length; i++) { ++ result.push(this.getValueInRange(ranges[i], editorCommon.EndOfLinePreference.TextDefined)); ++ } ++ ++ return result.join(newLineCharacter); ++ } ++ } ++ ++ public getHTMLToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string { ++ let rules: { [key: string]: string } = {};",please leave a TODO here so we clean this up once the minimap branch gets merged in (same as above),2017-02-16 15:55:11 +517,"@@ -56,6 +60,12 @@ export class DebugEditorContribution implements IDebugEditorContribution { + this.hideHoverScheduler = new RunOnceScheduler(() => this.hoverWidget.hide(), HOVER_DELAY); + this.registerListeners(); + this.breakpointWidgetVisible = CONTEXT_BREAKPOINT_WIDGET_VISIBLE.bindTo(contextKeyService); ++ ++ // TODO: How do I register a new decoration type using exposed api ?","You do not need to do any of this. Just by calling editor.deltaDecorations editor should register you decoration nicely. +When removing decorations you will also use ids of each of the added decorations by calling deltaDecoraitons.",2016-11-28 10:27:42 +620,"@@ -56,8 +56,7 @@ export class KillTerminalAction extends Action { + } + + /** +- * Copies the terminal selection. Note that since the command palette takes focus from the terminal,",This comment seems obsolete to me. Let me know if i'm missing something.,2016-12-18 22:50:04 +622,"@@ -56,8 +56,7 @@ export class KillTerminalAction extends Action { + } + + /** +- * Copies the terminal selection. Note that since the command palette takes focus from the terminal, +- * this can only be triggered via a keybinding. ++ * Copies the terminal selection.","The comment is still relevant as you can't trigger it through the command palette. This is what it should probably say though: + +```js +/** + * Copies the terminal selection. Note that since the command palette takes focus from the terminal, + * this cannot be triggered through the command palette. + */ +```",2016-12-19 05:31:33 +134,"@@ -560,7 +560,7 @@ export abstract class BaseGlobalNewAction extends Action { + } + + /* Create new file from anywhere: Open untitled */ +-export class GlobalNewFileAction extends Action { ++export class GlobalNewUntitledFileAction extends Action { + public static ID = 'workbench.action.files.newUntitledFile'; + public static LABEL = nls.localize('newFile', ""New File"");","Should this maybe read ""New Untitled File"" to make the difference clear? +",2016-04-21 11:12:56 +632,"@@ -566,11 +582,32 @@ + fenced_code_block_basic + + begin +- (^|\G)\s*(([`~]){3,})\s*(html|htm|shtml|xhtml|inc|tmpl|tpl)(\s+.*)?$ ++ (^|\G)\s*([`~]{3,})\s*(html|htm|shtml|xhtml|inc|tmpl|tpl)\n",Keep the `(\s+.*)?$`bit. We allow arbitrary text on the rest of the line after the language identifier to support passing other attributes (like line numbers specifiers) that some markdown engines support.,2016-12-20 23:31:27 +633,"@@ -566,11 +582,32 @@ + fenced_code_block_basic + + begin +- (^|\G)\s*(([`~]){3,})\s*(html|htm|shtml|xhtml|inc|tmpl|tpl)(\s+.*)?$ ++ (^|\G)\s*([`~]{3,})\s*(html|htm|shtml|xhtml|inc|tmpl|tpl)\n + name + markup.fenced_code.block.markdown +- while +- (^|\G)(?!\s*\2\3*\s*$) ++ end ++ (^|\G)\s*([`~]{3,})\n",This should also reverted to how it was before so that we consume any number of spaces after the fence end and the end of line.,2016-12-20 23:32:17 +762,"@@ -569,6 +569,9 @@ export class TerminalInstance implements ITerminalInstance { + env['PTYCOLS'] = cols.toString(); + env['PTYROWS'] = rows.toString(); + } ++ if (!env['LANG']) {","I think it's a good idea to have a fallback, but this would probably be better in `_getLangEnvVariable` instead, replacing the `n === 0` case :+1: ",2017-02-20 20:34:02 +133,"@@ -57,7 +57,7 @@ const category = nls.localize('filesCategory', ""Files""); + + let workbenchActionsRegistry = Registry.as(ActionExtensions.WorkbenchActions); + workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(SaveFileAsAction, SaveFileAsAction.ID, SaveFileAsAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S }), category, ['save', 'as']); +-workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(GlobalNewFileAction, GlobalNewFileAction.ID, GlobalNewFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_N }), category, ['new', 'file']); ++workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(GlobalNewUntitledFileAction, GlobalNewUntitledFileAction.ID, GlobalNewUntitledFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_N }), category, ['new', 'file']);","Maybe add the ""untitled"" to the keywords? +",2016-04-21 11:12:17 +282,"@@ -57,7 +61,15 @@ export class LineNumbersOverlay extends DynamicViewOverlay { + return true; + } + public onCursorPositionChanged(e:editorCommon.IViewCursorPositionChangedEvent): boolean { +- return false; ++ let modelPosition = this._context.model.convertViewPositionToModelPosition(e.position.lineNumber, e.position.column); ++ ++ if (!this._relativeLineNumbers || this._currentLineNumber === modelPosition.lineNumber) { ++ return false; ++ } ++ ++ this._currentLineNumber = modelPosition.lineNumber;","In the case where `this._relativeLineNumbers` is `false`, `this._currentLineNumber` should still be assigned such that `this._currentLineNumber` always has a good value. + +It is possible that the `relativeLineNumbers` option changes at runtime and in that case we'd want `this._currentLineNumber` to be up-to-date. +",2016-09-21 06:06:24 +865,"@@ -575,6 +575,7 @@ export interface IFilesConfiguration { + exclude: glob.IExpression; + watcherExclude: { [filepattern: string]: boolean }; + encoding: string; ++ defaultLanguage: string;",We do have an extension running that provides intellisense inside settings. For this setting I would like to see the list of language Ids when the user wants to quickly select a known language. The place to add this is here: https://github.com/Microsoft/vscode/blob/master/extensions/configuration-editing/src/settingsDocumentHelper.ts#L26,2017-03-25 23:55:11 +680,"@@ -58,12 +59,19 @@ export enum TextEditorRevealType { + InCenterIfOutsideViewport = 2 + } + +-export interface IApplyEditsOptions { ++export interface IUndoStopOptions { + undoStopBefore: boolean; + undoStopAfter: boolean; ++} ++ ++export interface IApplyEditsOptions extends IUndoStopOptions { + setEndOfLine: EndOfLine; + } + ++export interface IInsertSnippetOptions extends IUndoStopOptions { ++",![](https://cdn.meme.am/Instance/Preview?imageID=10051184&generatorTypeID=&panels=&text0=Machete&text1=don't%20do%20empty%20interface&text2=&text3=),2017-01-18 10:32:49 +717,"@@ -58,4 +67,27 @@ export class MainThreadMessageService extends MainThreadMessageServiceShape { + }); + }); + } ++ ++ private showModalMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable { ++ let closeAffordanceIndex = -1;",Just keep a `boolean`? I do not see `closeAffordanceIndex` being used for anything but that. Or is that an oversight?,2017-02-02 16:00:54 +474,"@@ -58,7 +68,7 @@ export interface IUntitledEditorService { + * It is valid to pass in a file resource. In that case the path will be used as identifier. + * The use case is to be able to create a new file with a specific path with VSCode. + */ +- createOrGet(resource?: URI, modeId?: string): UntitledEditorInput; ++ createOrGet(resource?: URI, modeId?: string, restoreResource?: URI): UntitledEditorInput;","@Tyriar maybe `restoreFromBackupResource` to make it clear this is about backups? +",2016-11-09 07:44:16 +28,"@@ -583,6 +586,63 @@ export class OneCursorOp { + return true; + } + ++ public static moveSubWordLeft(cursor:OneCursor, inSelectionMode: boolean, ctx: IOneCursorOperationContext): boolean { ++ let position = cursor.getPosition(); ++ var lineNumber = position.lineNumber;","Use `const` as much as possible. If the value changes, like `positionFound` at L608, use `let`. Try to avoid `var`. + +Tough I noticed Microsoft isn't doing this everytime as well. But it's best practice :). +",2015-12-11 13:11:48 +964,"@@ -586,6 +586,7 @@ export class CodeMenu { + const output = this.createMenuItem(nls.localize({ key: 'miToggleOutput', comment: ['&& denotes a mnemonic'] }, ""&&Output""), 'workbench.action.output.toggleOutput'); + const debugConsole = this.createMenuItem(nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, ""De&&bug Console""), 'workbench.debug.action.toggleRepl'); + const integratedTerminal = this.createMenuItem(nls.localize({ key: 'miToggleIntegratedTerminal', comment: ['&& denotes a mnemonic'] }, ""&&Integrated Terminal""), 'workbench.action.terminal.toggleTerminal'); ++ const taskMenu = this.createMenuItem(nls.localize({ key: 'miShowTask', comment: ['&& denotes a mnemonic'] }, ""&&Show Tasks...""), 'workbench.action.showTasks');","The && mnemonic is the letter that gets underlined on windows, then you can open the menu with alt+that letter. Looks like S is taken by Search, maybe use T",2017-06-12 21:22:52 +696,"@@ -588,6 +589,25 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom + return; + } + ++ if (handlerId === editorCommon.Handler.Paste) { ++ if (!this.cursor || typeof payload.text !== 'string' || payload.text.length === 0) { ++ // nothing to do ++ return; ++ } ++ const startPosition = this.cursor.getSelection().getStartPosition(); ++ this.cursor.trigger(source, handlerId, payload); ++ const endPosition = this.cursor.getSelection().getStartPosition(); ++ if (source === 'keyboard') { ++ this.emit(editorCommon.EventType.DidPaste, {",I would prefer for the editor to always give out rich objects (i.e. `Range` and not `IRange`). It does so for all non-serializable events.,2017-01-19 15:37:45 +780,"@@ -59,6 +59,31 @@ export class CloseEditorAction extends Action { + } + } + ++export class ForceCloseEditorAction extends Action {",Suggest to move this into `editorActions.ts`,2017-03-01 05:15:11 +779,"@@ -59,6 +59,31 @@ export class CloseEditorAction extends Action { + } + } + ++export class ForceCloseEditorAction extends Action { ++ ++ public static ID = 'workbench.action.forceCloseActiveEditor';",Maybe better `workbench.action.revertAndCloseActiveEditor` ?,2017-03-01 05:14:33 +781,"@@ -59,6 +59,31 @@ export class CloseEditorAction extends Action { + } + } + ++export class ForceCloseEditorAction extends Action { ++ ++ public static ID = 'workbench.action.forceCloseActiveEditor'; ++ public static LABEL = nls.localize('forceCloseActiveEditor', ""Force Close Editor"");",`Revert and Close Editor`,2017-03-01 05:15:28 +20,"@@ -59,7 +59,8 @@ + "".xml"", + "".xpdl"", + "".xsd"", +- "".xul""","H +H +",2015-12-01 12:17:19 +238,"@@ -596,6 +596,14 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp + return viewModel.convertViewRangeToModelRange(currentCenteredViewRange); + } + ++ public getVisibleRangeInViewport(): Range { ++ if (this._isDisposed) { ++ throw new Error('ViewImpl.getVisibleRangeInViewport: View is disposed'); ++ } ++ let visibleRange= this.layoutProvider.getLinesViewportData().visibleRange;","spacing around `=` +",2016-07-20 13:25:04 +181,"@@ -6,10 +6,12 @@ + { + ""label.closeButton"": ""关闭"", + ""label.find"": ""查找"", +- ""label.matchesLocation"": ""第 {0} 个(共 {1} 个)"", ++ ""label.matchesLocation"": ""{0} / {1}"", + ""label.nextMatchButton"": ""下一个匹配"", + ""label.noResults"": ""无结果"", + ""label.previousMatchButton"": ""上一个匹配"", ++ ""label"".allMatchButton"": ""选中所有匹配"",","I think we don't modify locaization files ourselves, only touch the English version. +",2016-06-12 04:12:09 +582,"@@ -6,10 +6,16 @@ + + import * as nls from 'vs/nls'; + import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes'; ++import { TPromise } from 'vs/base/common/winjs.base'; ++import { isFalsyOrEmpty } from 'vs/base/common/arrays'; + import { SortLinesCommand } from 'vs/editor/contrib/linesOperations/common/sortLinesCommand'; ++import { getDocumentRangeFormattingEdits } from 'vs/editor/contrib/format/common/format'; ++import { EditOperationsCommand } from 'vs/editor/contrib/format/common//formatCommand';",two slashes here -> vs/editor/contrib/format/common//formatCommand,2016-12-05 17:04:48 +567,"@@ -6,12 +6,17 @@ + 'use strict'; + + import DOM = require('vs/base/browser/dom'); ++import { onUnexpectedError } from 'vs/base/common/errors'; + import { defaultGenerator } from 'vs/base/common/idGenerator'; + import { escape } from 'vs/base/common/strings'; ++import URI from 'vs/base/common/uri'; + import { TPromise } from 'vs/base/common/winjs.base'; + import { IHTMLContentElement, MarkedString } from 'vs/base/common/htmlContent'; + import { marked } from 'vs/base/common/marked/marked'; + import { IMouseEvent } from 'vs/base/browser/mouseEvent'; ++import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';",layer breaker,2016-12-05 13:56:12 +568,"@@ -6,12 +6,17 @@ + 'use strict'; + + import DOM = require('vs/base/browser/dom'); ++import { onUnexpectedError } from 'vs/base/common/errors'; + import { defaultGenerator } from 'vs/base/common/idGenerator'; + import { escape } from 'vs/base/common/strings'; ++import URI from 'vs/base/common/uri'; + import { TPromise } from 'vs/base/common/winjs.base'; + import { IHTMLContentElement, MarkedString } from 'vs/base/common/htmlContent'; + import { marked } from 'vs/base/common/marked/marked'; + import { IMouseEvent } from 'vs/base/browser/mouseEvent'; ++import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer'; ++import { IModeService } from 'vs/editor/common/services/modeService';",same,2016-12-05 13:56:23 +569,"@@ -6,12 +6,17 @@ + 'use strict'; + + import DOM = require('vs/base/browser/dom'); ++import { onUnexpectedError } from 'vs/base/common/errors'; + import { defaultGenerator } from 'vs/base/common/idGenerator'; + import { escape } from 'vs/base/common/strings'; ++import URI from 'vs/base/common/uri'; + import { TPromise } from 'vs/base/common/winjs.base'; + import { IHTMLContentElement, MarkedString } from 'vs/base/common/htmlContent'; + import { marked } from 'vs/base/common/marked/marked'; + import { IMouseEvent } from 'vs/base/browser/mouseEvent'; ++import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer'; ++import { IModeService } from 'vs/editor/common/services/modeService'; ++import { IOpenerService } from 'vs/platform/opener/common/opener';",same,2016-12-05 13:56:32 +217,"@@ -6,40 +6,31 @@ + .monaco-editor .margin-view-overlays .folding { + margin-left: 5px; + cursor: pointer; +-} +- +-.monaco-editor .margin-view-overlays .folding::after { + background-repeat: no-repeat;","why are these changes part of this PR? Is the change in the editor core forcing these changes? +",2016-07-14 09:39:57 +756,"@@ -6,6 +6,8 @@ + .monaco-editor .zone-widget .zone-widget-container.breakpoint-widget { + height: 30px !important; + display: flex;",Try to put it in one rule together,2017-02-20 14:16:34 +65,"@@ -6,7 +6,7 @@ + ""contributes"": { + ""languages"": [{ + ""id"": ""html"", +- ""extensions"": [ "".html"", "".htm"", "".shtml"", "".mdoc"", "".jsp"", "".asp"", "".aspx"", "".jshtm"" ], ++ ""extensions"": [ "".html"", "".htm"", "".shtml"", "".xhtml"", "".mdoc"", "".jsp"", "".asp"", "".aspx"", "".jshtm"" ], + ""aliases"": [ ""HTML"", ""htm"", ""html"", ""xhtml"" ], + ""mimetypes"": [""text/html"", ""text/x-jshtm"", ""text/template"", ""text/ng-template""]","Oh you should also probably add `application/xhtml+xml` to this list. +",2016-02-29 22:56:59 +1,"@@ -6,7 +6,7 @@ + ""contributes"": { + ""languages"": [{ + ""id"": ""powershell"", +- ""extensions"": [ "".ps1"", "".psm1"", "".psd1"" ], ++ ""extensions"": [ "".ps1"", "".psm1"", "".psd1"", "".pssc"", "".psrc"" ],","Remove the space before `"".ps1""` +",2015-11-19 22:03:13 +916,"@@ -60,6 +60,26 @@ class CheckoutRemoteHeadItem extends CheckoutItem { + } + } + ++class BranchDeleteItem implements QuickPickItem { ++ ++ protected get shortCommit(): string { return (this.ref.commit || '').substr(0, 8); } ++ protected get treeish(): string | undefined { return this.ref.name; } ++ get label(): string { return this.ref.name || this.shortCommit; } ++ get description(): string { return this.shortCommit; } ++ ++ constructor(protected ref: Ref) { } ++ ++ async run(model: Model): Promise { ++ const ref = this.treeish; ++ ++ if (!ref) { ++ return; ++ } ++ ++ await model.deleteBranch(ref);","A common error from this operation happens when the branch isn't yet merged: + +![image](https://cloud.githubusercontent.com/assets/22350/25742311/24ce0144-318f-11e7-96ea-81dfbf6f3d5d.png) + +It would be great if the underlying git library would catch this situation, wrap it neatly in a `GitError` with a new `GitErrorCode` and we `try catch` it here, prompting the user `Hey, the branch isn't yet merge. Do you still want to delete it?`.",2017-05-05 10:35:08 +311,"@@ -602,6 +605,18 @@ export class WindowsManager implements IWindowsService { + iPathsToOpen = this.cliToPaths(openConfig.cli, ignoreFileNotFound); + } + ++ // Add any existing backup workspaces ++ if (openConfig.restoreBackups) { ++ // TODO: Ensure the workspaces being added actually have backups ++ this.backupService.getBackupWorkspaces().forEach(ws => {","What if a window is already opened with a workspace that has backup files, I think you need to avoid opening those again (since we prevent opening the same workspace twice we would just focus that window). +",2016-10-13 15:00:12 +934,"@@ -61,11 +64,25 @@ function registerSettingsCompletions(): vscode.Disposable { + }); + } + +-function newSimpleCompletionItem(text: string, range: vscode.Range, description?: string): vscode.CompletionItem { ++function registerExtensionsCompletions(): vscode.Disposable { ++ return vscode.languages.registerCompletionItemProvider({ pattern: '**/extensions.json' }, { ++ provideCompletionItems(document, position, token) { ++ const location = getLocation(document.getText(), document.offsetAt(position)); ++ const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); ++ if (location.path[0] === 'recommendations') { ++ return vscode.extensions.all",What do you suggest if there are no installed extensions?,2017-05-12 09:21:44 +935,"@@ -61,11 +64,25 @@ function registerSettingsCompletions(): vscode.Disposable { + }); + } + +-function newSimpleCompletionItem(text: string, range: vscode.Range, description?: string): vscode.CompletionItem { ++function registerExtensionsCompletions(): vscode.Disposable { ++ return vscode.languages.registerCompletionItemProvider({ pattern: '**/extensions.json' }, { ++ provideCompletionItems(document, position, token) { ++ const location = getLocation(document.getText(), document.offsetAt(position)); ++ const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); ++ if (location.path[0] === 'recommendations') { ++ return vscode.extensions.all ++ .filter(e => !e.id.startsWith('vscode.'))","- You also need to exclude following extension which is packaged along with VS Code - `Microsoft.vscode-markdown`. This was getting shown in the intelli-sense. + +- Intelli-sense should not show already entered extensions. ",2017-05-15 14:46:39 +933,"@@ -61,11 +64,25 @@ function registerSettingsCompletions(): vscode.Disposable { + }); + } + +-function newSimpleCompletionItem(text: string, range: vscode.Range, description?: string): vscode.CompletionItem { ++function registerExtensionsCompletions(): vscode.Disposable { ++ return vscode.languages.registerCompletionItemProvider({ pattern: '**/extensions.json' }, { ++ provideCompletionItems(document, position, token) { ++ const location = getLocation(document.getText(), document.offsetAt(position)); ++ const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); ++ if (location.path[0] === 'recommendations') { ++ return vscode.extensions.all ++ .filter(e => e.id.indexOf('vscode') === -1)",is this should ne `e.id.startsWith('vscode.')`?,2017-05-12 09:21:02 +937,"@@ -61,11 +64,32 @@ function registerSettingsCompletions(): vscode.Disposable { + }); + } + +-function newSimpleCompletionItem(text: string, range: vscode.Range, description?: string): vscode.CompletionItem { ++function registerExtensionsCompletions(): vscode.Disposable { ++ return vscode.languages.registerCompletionItemProvider({ pattern: '**/extensions.json' }, { ++ provideCompletionItems(document, position, token) { ++ const location = getLocation(document.getText(), document.offsetAt(position)); ++ const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); ++ if (location.path[0] === 'recommendations') { ++ const config = vscode.workspace && vscode.workspace.getConfiguration('extensions.json');","I do not think`vscode.workspace.getConfiguration('extensions.json')` will get the extension recommendations. +You might have to read the document and parse it. You already have document with text, so you can just use parse from `jsonc-parser` to get the existing recommendations.",2017-05-16 16:29:05 +32,"@@ -61,28 +61,28 @@ export class ActivitybarPart extends Part implements IActivityService { + private registerListeners(): void { + + // Activate viewlet action on opening of a viewlet +- this.toUnbind.push(this.eventService.addListener(EventType.VIEWLET_OPENING, (e: ViewletEvent) => this.onViewletOpening(e))); ++ this.toUnbind.push(this.eventService.addListener(EventType.VIEWLET_OPENING, (e: CompositeEvent) => this.onViewletOpening(e)));","@isidorn I think we can generalize this event to be COMPOSITE_OPENING and onCompositeOpening() because the listener seems to use the ID of the composite to do something and it also seems to be the only client through out the workbench. +",2016-01-15 15:02:19 +968,"@@ -610,6 +610,9 @@ class TaskService extends EventEmitter implements ITaskService { + + private registerCommands(): void { + CommandsRegistry.registerCommand('workbench.action.tasks.runTask', (accessor, arg) => {",If I run the build task with cmd+shift+b does this get called?,2017-06-12 21:48:02 +945,"@@ -62,10 +68,24 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri + return STATUS_BAR_NO_FOLDER_BACKGROUND; + } + +- // debugging ++ // Debugging + return STATUS_BAR_DEBUGGING_BACKGROUND; + } + ++ private getForegroundColorKey(): string {","This looks almost identical to `getBackgroundColorKey`. Can we just have one method where all color keys are passed in? Something like `getColorKey(noFolderColor, debuggingColor, normalColor)`?",2017-05-22 04:50:06 +635,"@@ -62,6 +65,7 @@ export interface ITerminalConfigHelper { + getFont(): ITerminalFont; + getFontLigaturesEnabled(): boolean; + getCursorBlink(): boolean; ++ isRightClickCopyPaste(): boolean;",Change this to `get...` like `getCursorBlink`,2016-12-21 03:01:49 +236,"@@ -622,15 +632,55 @@ export class OneCursorOp { + validatedViewPosition = cursor.convertModelPositionToViewPosition(validatedPosition.lineNumber, validatedPosition.column); + } + ++ return this.move(cursor, inSelectionMode, validatedViewPosition, eventSource, ctx); ++ } ++ ++ public static move(cursor:OneCursor, inSelectionMode: boolean, to:editorCommon.IPosition | string, eventSource: string, ctx: IOneCursorOperationContext): boolean {","please move argument decoding to `cursor.ts` to do it only once even if there are 1000 cursors. + +Please also make it clear which one is cursorMove and which one is the old one. They are all called move now. +",2016-07-15 11:26:08 +237,"@@ -622,15 +632,55 @@ export class OneCursorOp { + validatedViewPosition = cursor.convertModelPositionToViewPosition(validatedPosition.lineNumber, validatedPosition.column); + } + ++ return this.move(cursor, inSelectionMode, validatedViewPosition, eventSource, ctx); ++ } ++ ++ public static move(cursor:OneCursor, inSelectionMode: boolean, to:editorCommon.IPosition | string, eventSource: string, ctx: IOneCursorOperationContext): boolean { ++ if (!to) { ++ illegalArgument('to'); ++ } ++ ++ if (types.isString(to)) { ++ return this._move(cursor, inSelectionMode, to, ctx); ++ } ++ ++ let viewPosition: editorCommon.IPosition= to;","space before equal pls +",2016-07-15 11:26:18 +573,"@@ -622,6 +622,10 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom + return this.model.deltaDecorations(oldDecorations, newDecorations, this.id); + } + ","Same as my previous comment. This PR should not touch anything in the editor land. + +As I commented earlier have you tried using editor.deltaDecoraitions which should automatically register a decoration. A nice use case of this api can be found [here](https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts#L97)",2016-12-05 14:49:47 +80,"@@ -624,11 +676,13 @@ export class Model extends ee.EventEmitter implements debug.IModel { + + public sourceIsUnavailable(source: Source): void { + Object.keys(this.threads).forEach(key => { +- this.threads[key].callStack.forEach(stackFrame => {","For some reason I had missed updating this reference to `callStack`. + +Just pointing out what we have changed today that wasn't in yesterday's commit and you hadn't commented on. +",2016-03-17 00:57:12 +255,"@@ -63,6 +66,8 @@ export class TerminalInstance { + event: 'input', + data: this.sanitizeInput(data) + }); ++ ++ console.log('this.terminalProcess.process.pid=' + this.terminalProcess.process.pid);","💥 +",2016-08-18 19:36:22 +527,"@@ -63,9 +63,10 @@ export class TerminalPanel extends Panel { + this._terminalService.setContainers(this.getContainer().getHTMLElement(), this._terminalContainer); + + this._register(this._themeService.onDidColorThemeChange(this._updateTheme.bind(this))); +- this._register(this._configurationService.onDidUpdateConfiguration(this._updateConfig.bind(this))); ++ this._register(this._configurationService.onDidUpdateConfiguration(this._updateFont.bind(this))); ++ this._updateFont(); + this._updateTheme(); +- this._updateConfig(); ++ this._terminalService.updateConfig();",I think this can safely be removed.,2016-11-28 19:11:06 +372,"@@ -639,18 +639,26 @@ export class WindowsManager implements IWindowsService { + iPathsToOpen = this.cliToPaths(openConfig.cli, ignoreFileNotFound); + } + +- // Add any existing backup workspaces ++ let configuration: IWindowConfiguration; ++ let openInNewWindow = openConfig.preferNewWindow || openConfig.forceNewWindow; ++ ++ // Restore any existing backup workspaces + if (openConfig.restoreBackups) { +- this.backupService.getWorkspaceBackupPathsSync().forEach(ws => { +- iPathsToOpen.push(this.toIPath(ws)); +- }); +- // Get rid of duplicates +- iPathsToOpen = arrays.distinct(iPathsToOpen, path => { +- if (!('workspacePath' in path)) { +- return path.workspacePath; +- } +- return platform.isLinux ? path.workspacePath : path.workspacePath.toLowerCase(); ++ const workspacesWithBackups = this.backupService.getWorkspaceBackupPathsSync();","As reported in a different issue that code should really move out of the `open()` method and only be used from the first startup code. Otherwise it makes it very hard to understand what this method is actually doing (it is already quite complex). +",2016-10-21 13:57:17 +534,"@@ -64,6 +67,14 @@ export class BackupFilesModel implements IBackupFilesModel { + return true; + } + ++ public getTextFiles(): string[] {","@Tyriar this is some crazy string magic that is not very robust, instead I suggest to use the `URI` apis we already have: use `URI.parse()` to convert the resource string into a `URI` and then you have access to `fsPath` and scheme to find out what you want.",2016-11-29 05:26:25 +645,"@@ -645,19 +645,40 @@ export class VSCodeWindow implements IVSCodeWindow { + + this.win.setFullScreen(willBeFullScreen); + +- // Windows & Linux: Hide the menu bar but still allow to bring it up by pressing the Alt key +- if (platform.isWindows || platform.isLinux) { +- if (willBeFullScreen) { +- this.setMenuBarVisibility(false); +- } else { +- this.setMenuBarVisibility(!this.storageService.getItem(VSCodeWindow.menuBarHiddenKey, false)); // restore as configured +- } +- } ++ // respect configured menu bar visibility",@bpasero I changed the existing behavior here. Does this make sense for you?,2016-12-23 15:18:38 +254,"@@ -65,15 +65,15 @@ export interface ITerminalService { + + close(): TPromise; + copySelection(): TPromise; +- createNew(): TPromise; +- focus(): TPromise; ++ createNew(name?: string): TPromise;","As a recommendation I'd return the `ITerminalPanel` here and move `setActive`, `show`, `dispose` etc in it - the services seems to become quite large. +",2016-08-18 19:35:52 +405,"@@ -65,6 +97,30 @@ export class ActivitybarPart extends Part implements IActivityService { + } + } + ++ getIsEnabledForRegisteredViewlets(): { [viewletId: string]: boolean } {","Add access modifier +",2016-10-24 15:41:53 +406,"@@ -65,6 +97,30 @@ export class ActivitybarPart extends Part implements IActivityService { + } + } + ++ getIsEnabledForRegisteredViewlets(): { [viewletId: string]: boolean } { ++ const result = {}; ++ for (let viewletId in this.registeredViewlets) { ++ result[viewletId] = (this.enabledExternalViewlets.indexOf(viewletId) !== -1); ++ } ++ return result; ++ } ++ ++ toggleViewlet(viewletId: string): void {","Add access modifier +",2016-10-24 15:41:57 +915,"@@ -650,6 +650,11 @@ export class Repository { + await this.run(args); + } + ++ async deleteBranch(name: string): Promise { ++ const args = ['branch', '-d', name];",Maybe we should be explicit with the branch name and use its full form `refs/heads/${name}` instead of simply `name`.,2017-05-05 10:33:26 +994,"@@ -651,12 +651,16 @@ export class List implements ISpliceable, IDisposable { + if (options.ariaLabel) { + this.view.domNode.setAttribute('aria-label', options.ariaLabel); + } ++ this.view.domNode.setAttribute('aria-setsize', this.length.toString());","Just make this `0`, to be explicit.",2017-06-19 14:39:42 +995,"@@ -651,12 +651,16 @@ export class List implements ISpliceable, IDisposable { + if (options.ariaLabel) { + this.view.domNode.setAttribute('aria-label', options.ariaLabel); + } ++ this.view.domNode.setAttribute('aria-setsize', this.length.toString()); + + this.style(options); + } + + splice(start: number, deleteCount: number, elements: T[] = []): void { +- this.eventBufferer.bufferEvents(() => this.spliceable.splice(start, deleteCount, elements)); ++ this.eventBufferer.bufferEvents(() => {",Return this to the old syntax.,2017-06-19 14:39:57 +651,"@@ -652,19 +652,40 @@ export class VSCodeWindow implements IVSCodeWindow { + + this.win.setFullScreen(willBeFullScreen); + +- // Windows & Linux: Hide the menu bar but still allow to bring it up by pressing the Alt key +- if (platform.isWindows || platform.isLinux) { +- if (willBeFullScreen) { +- this.setMenuBarVisibility(false); +- } else { +- this.setMenuBarVisibility(!this.storageService.getItem(VSCodeWindow.menuBarHiddenKey, false)); // restore as configured +- } +- } ++ // respect configured menu bar visibility ++ const windowConfig = this.configurationService.getConfiguration('window'); ++ this.setMenuBarVisibility(windowConfig && windowConfig.menuBarVisibility, false); + } + +- public setMenuBarVisibility(visible: boolean): void { +- this.win.setMenuBarVisibility(visible); +- this.win.setAutoHideMenuBar(!visible); ++ public setMenuBarVisibility(visibility: '' | 'visible' | 'toggle' | 'hidden', notify: boolean = true): void { ++ ++ switch (visibility) { ++ case ('visible'): { ++ this.win.setMenuBarVisibility(true); ++ this.win.setAutoHideMenuBar(false); ++ break; ++ } ++ case ('toggle'): { ++ this.win.setMenuBarVisibility(false); ++ this.win.setAutoHideMenuBar(true); ++ ++ if (notify) { ++ this.send('vscode:showInfoMessage', nls.localize('hiddenMenuBar', ""You can still access the menu bar by pressing the **Alt** key."")); ++ }; ++ break; ++ } ++ case ('hidden'): { ++ this.win.setMenuBarVisibility(false); ++ this.win.setAutoHideMenuBar(false); ++ break; ++ } ++ default: {",@xwvvvvwx can we merge this with the 'visible' case? that avoids code duplication here.,2017-01-04 10:54:12 +992,"@@ -656,7 +656,10 @@ export class List implements ISpliceable, IDisposable { + } + + splice(start: number, deleteCount: number, elements: T[] = []): void { +- this.eventBufferer.bufferEvents(() => this.spliceable.splice(start, deleteCount, elements)); ++ this.eventBufferer.bufferEvents(() => { ++ this.spliceable.splice(start, deleteCount, elements); ++ this.view.domNode.setAttribute('aria-setsize', this.length.toString());","You should do this outside the event buffering. + +Shouldn't there be an initial value for this, before any `splice` is called?",2017-06-19 14:28:57 +186,"@@ -658,6 +662,22 @@ + + + ++ fenced_code_block_php ++ ++ begin ++ (^|\G)\s*([`~]{3,})\s*(php|php3|php4|php5|phpt|phtml|aw|ctp)\s*$ ++ name ++ markup.fenced_code.block.markdown ++ end ++ (^|\G)(\2)\n ++ patterns ++ ++ ++ include ++ text.html.php","It's the same as the scopeName inside php syntax file, but currently the inline highlighting doesn't work. Will look into it later on. +",2016-06-20 09:36:02 +823,"@@ -66,6 +66,10 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(Toggle + if (isWindows || isLinux) { + workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMenuBarAction, ToggleMenuBarAction.ID, ToggleMenuBarAction.LABEL), 'View: Toggle Menu Bar', viewCategory); + } ++workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigateUpAction, NavigateUpAction.ID, NavigateUpAction.LABEL, null), 'View: Move to the View Part above', viewCategory);","@misoguy please use capital casing here, e.g. `View: Move to the View Part Above`",2017-03-14 05:40:24 +808,"@@ -66,6 +66,10 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(Toggle + if (isWindows || isLinux) { + workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMenuBarAction, ToggleMenuBarAction.ID, ToggleMenuBarAction.LABEL), 'View: Toggle Menu Bar', viewCategory); + } ++workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigateUpAction, NavigateUpAction.ID, NavigateUpAction.LABEL, null), 'View: Navigate Up', viewCategory);","I wonder if the command name is verbose enough to understand the intent. Can we see how others (VIM?) name this command? Maybe ""Navigate to next View to the Left"" etc?",2017-03-10 05:45:35 +321,"@@ -66,6 +68,7 @@ export class DirtyFilesTracker implements IWorkbenchContribution { + } + + private onUntitledDidChangeDirty(resource: URI): void { ++","I prefer to not add empty lines in the beginning of a method, please stick to the coding format used elsewhere in the files. +",2016-10-13 15:13:17 +163,"@@ -67,11 +72,23 @@ const DEFAULT_ANSI_COLORS = { + ] + }; + ++export interface ITerminalFont { ++ fontFamily: string; ++ fontSize: number; ++ lineHeight: number; ++ charWidth: number; ++ charHeight: number; ++} ++ + /** + * Encapsulates terminal configuration logic, the primary purpose of this file is so that platform + * specific test cases can be written. + */ + export class TerminalConfigHelper { ++ private characterMeasureElement: HTMLElement;","Name `charMeasureElement` for consistency +",2016-06-02 06:46:40 +172,"@@ -67,34 +69,73 @@ const DEFAULT_ANSI_COLORS = { + ] + }; + ++export interface ITerminalFont { ++ fontFamily: string; ++ fontSize: number; ++ lineHeight: number; ++ charWidth: number; ++ charHeight: number; ++} ++ + /** + * Encapsulates terminal configuration logic, the primary purpose of this file is so that platform + * specific test cases can be written. + */ + export class TerminalConfigHelper { ++ private charMeasureElement: HTMLElement; ++ + public constructor( + private platform: Platform, + private configurationService: IConfigurationService, +- private themeService: IThemeService) { ++ private themeService: IThemeService, ++ private parentDomElement: HTMLElement) { + } + + public getTheme(): string[] { + let baseThemeId = getBaseThemeId(this.themeService.getTheme()); + return DEFAULT_ANSI_COLORS[baseThemeId]; + } + ++ private neasureFont(fontFamily: string, fontSize: number, lineHeight: number): ITerminalFont { ++ if (!this.charMeasureElement) { ++ this.charMeasureElement = new Builder(this.parentDomElement, true).div().build().getHTMLElement(); ++ } ++ let style = this.charMeasureElement.style; ++ style.display = 'inline';","Will this flicker the element on the screen? Should it be positioned absolutely off screen? +",2016-06-02 20:19:31 +177,"@@ -67,34 +69,73 @@ const DEFAULT_ANSI_COLORS = { + ] + }; + ++export interface ITerminalFont { ++ fontFamily: string; ++ fontSize: number; ++ lineHeight: number; ++ charWidth: number; ++ charHeight: number; ++} ++ + /** + * Encapsulates terminal configuration logic, the primary purpose of this file is so that platform + * specific test cases can be written. + */ + export class TerminalConfigHelper { ++ private charMeasureElement: HTMLElement; ++ + public constructor( + private platform: Platform, + private configurationService: IConfigurationService, +- private themeService: IThemeService) { ++ private themeService: IThemeService, ++ private parentDomElement: HTMLElement) { + } + + public getTheme(): string[] { + let baseThemeId = getBaseThemeId(this.themeService.getTheme()); + return DEFAULT_ANSI_COLORS[baseThemeId]; + } + ++ private neasureFont(fontFamily: string, fontSize: number, lineHeight: number): ITerminalFont { ++ if (!this.charMeasureElement) { ++ this.charMeasureElement = new Builder(this.parentDomElement, true).div().build().getHTMLElement(); ++ } ++ let style = this.charMeasureElement.style; ++ style.display = 'inline'; ++ style.fontFamily = fontFamily; ++ style.fontSize = fontSize + 'px'; ++ style.lineHeight = lineHeight + 'px'; ++ this.charMeasureElement.innerText = 'X'; ++ let rect = this.charMeasureElement.getBoundingClientRect(); ++ style.display = 'none'; ++ let charWidth = Math.ceil(rect.width); ++ let charHeight = Math.ceil(rect.height); ++ return { ++ fontFamily, ++ fontSize, ++ lineHeight, ++ charWidth, ++ charHeight ++ }; ++ } ++ + /** +- * Set the terminal font to `terminal.integrated.fontFamily` if it is set, otherwise fallback to +- * `editor.fontFamily`. ++ * Gets the font information based on the terminal.integrated.fontFamily, ++ * terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties + */ +- public getFontFamily(): string { +- let terminalConfig = this.configurationService.getConfiguration(); +- let fontFamily = terminalConfig.terminal.integrated.fontFamily; +- if (!fontFamily) { +- let editorConfig = this.configurationService.getConfiguration(); +- fontFamily = editorConfig.editor.fontFamily; ++ public getFont(): ITerminalFont { ++ let terminalConfig = this.configurationService.getConfiguration().terminal.integrated; ++ let editorConfig = this.configurationService.getConfiguration(); ++ ++ let fontFamily = terminalConfig.fontFamily || editorConfig.editor.fontFamily; ++ let fontSize = this.toInteger(terminalConfig.fontSize, 0) || editorConfig.editor.fontSize; ++ let lineHeight = this.toInteger(terminalConfig.lineHeight, 0) || editorConfig.editor.lineHeight; ++ ++ if (lineHeight === 0) { ++ lineHeight = Math.round(GOLDEN_LINE_HEIGHT_RATIO * fontSize);","We basically want consistency with how editor.lineHeight works here, is this how that falls back? +",2016-06-02 20:36:11 +592,"@@ -67,4 +67,118 @@ suite('Editor Contrib - Line Operations', () => { + assert.equal(model.getLineContent(5), 'horlworld', '005'); + }); + }); ++ ++ test('Join lines', function () { ++ withMockCodeEditor( ++ [ ++ 'hello', ++ 'world', ++ 'hello ', ++ 'world', ++ 'hello ', ++ ' world', ++ 'hello ', ++ ' world', ++ '', ++ '', ++ 'hello world' ++ ], {}, (editor, cursor) => { ++ let model = editor.getModel(); ++ let joinLinesAction = new JoinLinesAction(); ++ ++ editor.setSelection(new Selection(1, 2, 1, 2)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(1), 'hello world', '001'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(1, 6, 1, 6).toString(), '002'); ++ ++ editor.setSelection(new Selection(2, 2, 2, 2)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(2), 'hello world', '003'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(2, 7, 2, 7).toString(), '004'); ++ ++ editor.setSelection(new Selection(3, 2, 3, 2)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(3), 'hello world', '005'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(3, 7, 3, 7).toString(), '006'); ++ ++ editor.setSelection(new Selection(4, 2, 5, 3)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(4), 'hello world', '007'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(4, 2, 4, 8).toString(), '008'); ++ ++ editor.setSelection(new Selection(5, 1, 7, 3)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(5), 'hello world', '009'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(5, 1, 5, 3).toString(), '010'); ++ }); ++ }); ++ ++ test('transpose', function () {","does it work for empty lines, or on empty files? + +You can use scripts\test.bat --coverage and my awesome LCOV plugin to see your code coverage ;)",2016-12-05 17:33:49 +591,"@@ -67,4 +67,118 @@ suite('Editor Contrib - Line Operations', () => { + assert.equal(model.getLineContent(5), 'horlworld', '005'); + }); + }); ++ ++ test('Join lines', function () { ++ withMockCodeEditor( ++ [ ++ 'hello', ++ 'world', ++ 'hello ', ++ 'world', ++ 'hello ', ++ ' world', ++ 'hello ', ++ ' world', ++ '', ++ '', ++ 'hello world' ++ ], {}, (editor, cursor) => { ++ let model = editor.getModel(); ++ let joinLinesAction = new JoinLinesAction(); ++ ++ editor.setSelection(new Selection(1, 2, 1, 2)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(1), 'hello world', '001'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(1, 6, 1, 6).toString(), '002'); ++ ++ editor.setSelection(new Selection(2, 2, 2, 2)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(2), 'hello world', '003'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(2, 7, 2, 7).toString(), '004'); ++ ++ editor.setSelection(new Selection(3, 2, 3, 2)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(3), 'hello world', '005'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(3, 7, 3, 7).toString(), '006'); ++ ++ editor.setSelection(new Selection(4, 2, 5, 3)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(4), 'hello world', '007'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(4, 2, 4, 8).toString(), '008'); ++ ++ editor.setSelection(new Selection(5, 1, 7, 3)); ++ joinLinesAction.run(null, editor); ++ assert.equal(model.getLineContent(5), 'hello world', '009'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(5, 1, 5, 3).toString(), '010'); ++ }); ++ }); ++ ++ test('transpose', function () { ++ withMockCodeEditor( ++ [ ++ 'hello world' ++ ], {}, (editor, cursor) => { ++ let model = editor.getModel(); ++ let transposeAction = new TransposeAction(); ++ ++ editor.setSelection(new Selection(1, 1, 1, 1)); ++ transposeAction.run(null, editor); ++ assert.equal(model.getLineContent(1), 'hello world', '001'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(1, 2, 1, 2).toString(), '002'); ++ ++ editor.setSelection(new Selection(1, 6, 1, 6)); ++ transposeAction.run(null, editor); ++ assert.equal(model.getLineContent(1), 'hell oworld', '003'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(1, 7, 1, 7).toString(), '004'); ++ ++ editor.setSelection(new Selection(1, 12, 1, 12)); ++ transposeAction.run(null, editor); ++ assert.equal(model.getLineContent(1), 'hell oworld', '005'); ++ assert.deepEqual(editor.getSelection().toString(), new Selection(1, 12, 1, 12).toString(), '006'); ++ } ++ ); ++ }); ++ ++ test('toggle case', function () {","add more tests, e.g. for empty lines or for the cursor in the middle of whitespace.",2016-12-05 17:32:39 +921,"@@ -67,6 +70,12 @@ export class TextFileEditor extends BaseTextEditor { + } + } + ++ private onWillCloseEditor(e: IEditorIdentifier): void { ++ if (e.editor === this.input && this.position === this.editorGroupService.getStacksModel().positionOfGroup(e.group)) {","It is fine to do the equality check here between editors here? They are actually the same reference? +I understand you do not have an `id` for the editors here. + +You also treat the input as FileEditorInput later on so I guess you could check their resource uri as comparison?",2017-05-10 08:23:13 +630,"@@ -67,7 +67,7 @@ export class PackageJSONContribution implements IJSONContribution { + let name = keys[0]; + let insertText = new SnippetString().appendText(JSON.stringify(name)); + if (addValue) { +- insertText.appendText(': ').appendPlaceholder('*'); ++ insertText.appendText(': ""').appendPlaceholder('').appendText('""'); + if (!isLast) {","should be `""*""`, not just `""""`",2016-12-20 08:32:22 +872,"@@ -670,7 +669,7 @@ export class ActionBar extends EventEmitter implements IActionRunner { + + public dispose(): void { + if (this.items !== null) { +- lifecycle.dispose(this.items); ++ this.clear();","Can we not do this for stable, but only on insiders? Seems like an additional change on top that is not needed to fix the actual issue.",2017-04-04 15:23:32 +914,"@@ -671,6 +677,29 @@ export class CommandCenter { + await this.model.branch(name); + } + ++ @command('git.merge') ++ async merge(): Promise { ++ const config = workspace.getConfiguration('git'); ++ const checkoutType = config.get('checkoutType') || 'all'; ++ const includeRemotes = checkoutType === 'all' || checkoutType === 'remote'; ++ ++ const heads = this.model.refs.filter(ref => ref.type === RefType.Head) ++ .map(ref => new CheckoutItem(ref)); ++ ++ const remoteHeads = (includeRemotes ? this.model.refs.filter(ref => ref.type === RefType.RemoteHead) : []) ++ .map(ref => new CheckoutRemoteHeadItem(ref)); ++ ++ const picks = [...heads, ...remoteHeads]; ++ const placeHolder = 'Select a ref to checkout';","Where's the `localize` call? Remember, Code needs to be localized for other languages. Also, the sentence is wrong. It should be something like `Select a branch to merge from`",2017-05-05 10:15:42 +494,"@@ -68,7 +68,7 @@ export interface IUntitledEditorService { + * It is valid to pass in a file resource. In that case the path will be used as identifier. + * The use case is to be able to create a new file with a specific path with VSCode. + */ +- createOrGet(resource?: URI, modeId?: string, restoreResource?: URI): UntitledEditorInput; ++ createOrGet(resource?: URI, modeId?: string, hasBackupToRestore?: boolean): UntitledEditorInput;","@Tyriar `hasBackupToRestore` is not being used after all? +",2016-11-16 14:30:34 +878,"@@ -699,6 +699,26 @@ declare module 'vscode' { + } + + /** ++ * Represents options to configure the behavior of showing a [document](#TextDocument) in an [editor](#TextEditor). ++ */ ++ export interface ShowTextDocumentOptions {","@jrieken I don't love this name, let me know what you think",2017-04-13 18:53:00 +900,"@@ -699,6 +699,26 @@ declare module 'vscode' { + } + + /** ++ * Represents options to configure the behavior of showing a [document](#TextDocument) in an [editor](#TextEditor). ++ */ ++ export interface TextDocumentShowOptions { ++ /** ++ * An optional view column in which the [editor](#TextEditor) should be shown. The default is the [one](#ViewColumn.One), other values are adjusted to be __Min(column, columnCount + 1)__. ++ */ ++ column ?: ViewColumn,",Wow - your commit should have been blocked because that's a formatting issue...,2017-04-25 13:56:23 +954,"@@ -7,11 +7,13 @@ import * as interfaces from './interfaces'; + import { DocumentMergeConflict } from './documentMergeConflict'; + + const startHeaderMarker = '<<<<<<< '; ++const commonAncestorsMarker = '||||||| '; + const splitterMarker = '======='; + const endFooterMarker = '>>>>>>> '; + + interface IScanMergedConflict { + startHeader: vscode.TextLine; ++ commonAncestors: vscode.TextLine | null;",Nit; might as well mark `commonAncestors` as optional e.g. `commonAncestors?`,2017-05-30 15:42:22 +911,"@@ -7,13 +7,10 @@ import * as nls from 'vs/nls'; + import { TPromise } from 'vs/base/common/winjs.base';","Looks good overall and I like we removed code from this class. + +I only have the issue that you are creating a `linkDetector` at every iteration in a loop. Would it not make sense just to create one global one for the replViewer and always to reuse it?",2017-05-05 09:46:06 +330,"@@ -7,13 +7,19 @@ + transform: rotate(180deg); + } + +-.monaco-workbench > .part.activitybar { ++.monaco-workbench > .part.activitybar, .monaco-workbench.mac.fullscreen.use-inline-toolbar > .part.activitybar {","I do not understand why this rule is duplicated here? +",2016-10-15 06:17:22 +785,"@@ -7,28 +7,20 @@ + + const fs = require('fs'); + const path = require('path'); ++const toDelete = new Set(['tsc.js', 'tsserverlibrary.js', 'typescript.js', 'typescriptServices.js']); + +-function removeFile(filePath) { +- try { +- fs.unlinkSync(filePath); +- console.log(`removed '${filePath}'`); +- } catch (e) { +- console.warn(e); ++const root = path.join(__dirname, 'node_modules', 'typescript', 'lib'); ++for (let name of fs.readdirSync(root)) { ++ if (name === 'lib.d.ts' || name.match(/^lib\..*\.d\.ts$/) || name === 'protocol.d.ts') { ++ continue; + }",Should we just use glob patterns to avoid the mix of `toDelete` and or-conditions?,2017-03-01 09:23:27 +74,"@@ -7,6 +7,11 @@ import assert = require('assert'); + import uri from 'vs/base/common/uri';","Really happy for the tests. +",2016-03-16 10:25:45 +7,"@@ -7,6 +7,7 @@ + ps1 + psm1 + psd1 ++ ps1xml","Same here, `/extensions/powershell/package.json` contains the file extensions +",2015-11-21 19:07:45 +951,"@@ -7,6 +7,7 @@ + ""license"": ""MIT"", + ""publisher"": ""vscode"", + ""aiKey"": ""AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217"", ++ ""enableProposedApi"": true,",No need to use proposed API here anymore. I moved the API to vscode.d.ts ,2017-05-23 19:14:38 +654,"@@ -7,6 +7,7 @@ + import { isLinux, isWindows } from 'vs/base/common/platform'; + import { fill } from 'vs/base/common/arrays'; + import { CharCode } from 'vs/base/common/charCode'; ++import { endsWith } from 'vs/base/common/strings';","Overall, can you please use `const` and `let` instead of `var` for variables?",2017-01-09 09:10:27 +6,"@@ -7,6 +7,9 @@ + clj + cljs + clojure ++ cljc ++ cljx ++ edn","If you want to add file extensions for clojure, you have to do that `/extensions/clojure/package.json`. From `/extensions/clojure/syntaxes/Clojure.tmLanguage` we only take the colorizer information. +",2015-11-21 19:07:06 +430,"@@ -70,4 +70,24 @@ export interface IActivityService { + * Clears activity shown in the activitybar for the given viewlet or panel. + */ + clearActivity(compositeId: string): void; +-} +\ No newline at end of file ++ ++ /** ++ * Get registered external viewlets' info for populating 'Toggle Custom Explorer' command picks. ++ */ ++ getInfoForRegisteredViewlets(): { ++ [viewletId: string]: { ++ isEnabled: boolean; ++ treeLabel: string; ++ } ++ }; ++ ++ /** ++ * Enable/disable an external viewlet. ++ */ ++ toggleViewlet(viewletId: string): void; ++ ++ /** ++ * Get the external viewlet id that is about to open. ++ */ ++ getExternalViewletIdToOpen(): string; ++}","[needs thinking] @bpasero will know better, but I have a strong feeling that the `IActivityService` isn't the right place for viewlet specifics. Isn't there an `IViewletService` and wouldn't that be the better place for this? +",2016-11-01 10:05:06 +447,"@@ -70,4 +71,19 @@ export interface IActivityService { + * Clears activity shown in the activitybar for the given viewlet or panel. + */ + clearActivity(compositeId: string): void; +-} +\ No newline at end of file ++","@octref this Viewlet related code should move into `IViewletService` or if that is impossible for some reason maybe into a new `IExtensionViewletService` +",2016-11-03 08:38:55 +919,"@@ -703,6 +703,7 @@ export class EditorStacksModel implements IEditorStacksModel { + private _onEditorDirty: Emitter; + private _onEditorLabelChange: Emitter; + private _onEditorOpened: Emitter; ++ private _onWillCloseEditor: Emitter; + private _onEditorClosed: Emitter; + private _onModelChanged: Emitter;","Why does `onWillCloseEditor` emit a different event than `onEditorClosed`? +Intuitivly they should emit the same and it makes sense to me that is the `EditorIdentififer`",2017-05-10 08:19:47 +301,"@@ -709,6 +718,17 @@ export class Workbench implements IPartService { + // Create Workbench DIV Off-DOM + this.workbenchContainer = $('.monaco-workbench-container'); + this.workbench = $().div({ 'class': 'monaco-workbench ' + (isWindows ? 'windows' : isLinux ? 'linux' : 'mac'), id: Identifiers.WORKBENCH_CONTAINER }).appendTo(this.workbenchContainer); ++ ++ // Only needed while the option `windowConfig.macOSUseInlineToolbar` exists ++ if (isMacintosh) {","Please move all of this code into `renderWorkbench` where we already adjust some CSS classes based on things like sidebar visible or not. It is also much easier to get hold of the IConfigurationService by adding the following to the constructor of the workbench: + +`@IConfigurationService private configurationService: IConfigurationService` + +All the other code is not needed then. + +To find out if the setting is set, I suggest this code: + +`this.configurationService.lookup('window.macOSUseInlineToolbar').value` +",2016-10-05 06:53:48 +437,"@@ -709,7 +709,18 @@ export class WindowsManager implements IWindowsService { + } + + // Handle folders to open +- let openInNewWindow = openConfig.preferNewWindow || openConfig.forceNewWindow; ++ let openInNewWindow: boolean;","@elemongw sorry, but this does not work for me when I try it. The folder opens in the same window no matter how I configure the setting. I believe you need to turn the logic around: set `openInNewWindow` to true when the setting is enabled! +",2016-11-03 07:31:33 +993,"@@ -712,6 +715,7 @@ export class List implements ISpliceable, IDisposable { + setFocus(indexes: number[]): void { + indexes = indexes.sort(numericSort); + this.focus.set(indexes); ++ this.view.domNode.setAttribute('aria-posinset', indexes.length ? (indexes[0] + 1).toString() : undefined);","The [w3 docs](https://www.w3.org/TR/wai-aria/states_and_properties#aria-posinset) state: + +> Authors MUST set the value for aria-posinset to an integer greater than or equal to 1, and less than or equal to the size of the set. + +Setting it to `undefined` doesn't sound like it's the right thing to do here.",2017-06-19 14:30:41 +637,"@@ -72,6 +72,11 @@ configurationRegistry.registerConfiguration({ + }, + 'default': [] + }, ++ 'terminal.integrated.rightClickCopyPaste': { ++ 'description': nls.localize('terminal.integrated.rightClickCopyPaste', ""Controls whether copy/paste happens on mouse right click in integrated terminal.""),","I think the description needs to be more detailed, how about this? + +> When set, this will prevent the context menu from appearing on right clicking in the terminal, instead it will copy when there is a selection and paste when there is no selection.",2016-12-21 03:07:43 +623,"@@ -72,6 +84,12 @@ configurationRegistry.registerConfiguration({ + }, + 'default': [] + }, ++ 'terminal.integrated.rightClickAction.windows': {","I'm thinking instead of having 3 settings for each platform and using strings, instead having a single setting for all platforms that just turns on rightClickCopy/Paste. Maybe `terminal.integrated.rightClickCopyPaste`? Then the default could be true when `platform.isWindows` (put the default in terminal.ts and import it into this file).",2016-12-19 05:33:46 +539,"@@ -72,8 +72,8 @@ export default class LinkedMap { + return item.value; + } + +- public shift(): T { +- if (!this.head && !this.tail) { ++ public shift(): T | undefined {",The idea why I used && here is that only having one being undefined / null basically points to a programming error somewhere else and the code should fail later on. Now that error might be covered up. I think if we go with a || here then we should add additional asserts.,2016-11-30 09:15:49 +551,"@@ -729,9 +744,16 @@ export class WindowsManager implements IWindowsMainService { + state: this.getNewWindowState(configuration), + extensionDevelopmentPath: configuration.extensionDevelopmentPath, + allowFullscreen: this.lifecycleService.wasUpdated || (windowConfig && windowConfig.restoreFullscreen), +- titleBarStyle: windowConfig ? windowConfig.titleBarStyle : void 0 ++ titleBarStyle: windowConfig ? windowConfig.titleBarStyle : void 0, ++ vscodeWindowId: configuration.vscodeWindowId + }); + ++ configuration.vscodeWindowId = vscodeWindow.vscodeWindowId; ++ if (!configuration.extensionDevelopmentPath) { ++ // TODO: Cover closing a folder/existing window case ++ this.backupService.pushEmptyWorkspaceBackupWindowIdSync(configuration.vscodeWindowId);",@Tyriar I suggest to move this up to the place where we already call `pushWorkspaceBackupPathsSync` so that we have it in one place. doing this from `toConfiguration` is very weird. As a caller of this method I would expect to get a configuration object but as a side effect I am writing to the backup folder??,2016-12-01 16:25:57 +289,"@@ -73,7 +73,7 @@ + ""menus"": { + ""editor/title"": [ + { +- ""when"": ""resourceLangId == markdown"", ++ ""when"": ""editorLangId == markdown"",","I could also change this to be `resourceLangId == markdown || editorLangId == markdown`, but only showing the preview menu item for files that are viewed as markdown makes more sense to me +",2016-09-22 18:14:49 +312,"@@ -730,6 +745,12 @@ export class WindowsManager implements IWindowsService { + // Emit events + iPathsToOpen.forEach(iPath => this.eventEmitter.emit(EventTypes.OPEN, iPath)); + ++ // Add to backups","Why are we adding these workspaces again to backup service? +",2016-10-13 15:01:36 +336,"@@ -736,6 +736,16 @@ export class Workbench implements IPartService { + // Create Workbench DIV Off-DOM + this.workbenchContainer = $('.monaco-workbench-container'); + this.workbench = $().div({ 'class': 'monaco-workbench ' + (isWindows ? 'windows' : isLinux ? 'linux' : 'mac'), id: Identifiers.WORKBENCH_CONTAINER }).appendTo(this.workbenchContainer); ++ ++ ++ // Mac specific UI changes ++ if (isMacintosh) { ++ const {serviceCollection} = this.workbenchParams;","Unused serviceCollection? +",2016-10-15 06:21:59 +337,"@@ -736,6 +736,16 @@ export class Workbench implements IPartService { + // Create Workbench DIV Off-DOM + this.workbenchContainer = $('.monaco-workbench-container'); + this.workbench = $().div({ 'class': 'monaco-workbench ' + (isWindows ? 'windows' : isLinux ? 'linux' : 'mac'), id: Identifiers.WORKBENCH_CONTAINER }).appendTo(this.workbenchContainer); ++ ++ ++ // Mac specific UI changes ++ if (isMacintosh) { ++ const {serviceCollection} = this.workbenchParams; ++ const windowConfig = this.configurationService.getConfiguration('window');","Instead of any, you should add the setting to https://github.com/Microsoft/vscode/blob/mac-titlebar-inline/src/vs/workbench/electron-browser/common.ts#L24 and use `IWindowConfiguration` properly. +",2016-10-15 06:22:42 +338,"@@ -736,6 +736,16 @@ export class Workbench implements IPartService { + // Create Workbench DIV Off-DOM + this.workbenchContainer = $('.monaco-workbench-container'); + this.workbench = $().div({ 'class': 'monaco-workbench ' + (isWindows ? 'windows' : isLinux ? 'linux' : 'mac'), id: Identifiers.WORKBENCH_CONTAINER }).appendTo(this.workbenchContainer); ++ ++ ++ // Mac specific UI changes ++ if (isMacintosh) { ++ const {serviceCollection} = this.workbenchParams; ++ const windowConfig = this.configurationService.getConfiguration('window'); ++ if (windowConfig.macOSUseInlineToolbar) {","`windowConfig` can be null if the user has a weird config +",2016-10-15 06:23:06 +299,"@@ -74,6 +74,11 @@ import {IEnvironmentService} from 'vs/platform/environment/common/environment'; + import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; + import * as watermark from 'vs/workbench/parts/watermark/watermark'; + ++// These three are used for the macOS inline toolbars option, and can be removed once default ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';","Can you make sure the formatting of imports matches the other imports? also I suggest to remove the comment for now, we will likely not make this default soon nor get rid of the setting if people don't like it. We still have to figure out how to run this experiment, maybe settings is not the best in the end. +",2016-10-05 06:51:28 +298,"@@ -74,6 +74,11 @@ import {IEnvironmentService} from 'vs/platform/environment/common/environment'; + import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; + import * as watermark from 'vs/workbench/parts/watermark/watermark'; + ++// These three are used for the macOS inline toolbars option, and can be removed once default ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; ++import { IWindowSettings } from 'vs/code/electron-main/window';","this is a layer break: we cannot depend from a VSCode window into the main process, please see https://github.com/Microsoft/vscode/wiki/Code-Organization +",2016-10-05 06:50:44 +682,"@@ -75,6 +75,10 @@ export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerE + description: nls.localize('vscode.extension.contributes.debuggers.languages', ""List of languages for which the debug extension could be considered the \""default debugger\"".""), + type: 'array' + }, ++ adapterExecutableCommand: {",argumnts is missing an E argumEnts,2017-01-18 14:02:37 +219,"@@ -76,6 +86,8 @@ export class OpenAnythingHandler extends QuickOpenHandler { + } + + public getResults(searchValue: string): TPromise { ++ const timerEvent = this.telemetryService.timedPublicLog('openAnything'); ++ const startTime = timerEvent.startTime ? timerEvent.startTime.getTime() : Date.now();","I find the check weird here, why would startTime be undefined if you got timerEvent from the timedPublicLog method? +",2016-07-14 17:33:48 +888,"@@ -76,8 +109,8 @@ export class TerminalLinkHandler { + this._handleLocalLink(url); + return; + }); ++ + return this._xterm.registerLinkMatcher(this._localLinkRegex, wrappedHandler, { +- matchIndex: 1,",Don't we need this?,2017-04-17 17:44:34 +892,"@@ -76,83 +76,96 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(Decrea + + // Configuration: Workbench + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); ++ ++let workbenchProperties: { [path: string]: IJSONSchema; } = { ++ 'workbench.editor.showTabs': { ++ 'type': 'boolean', ++ 'description': nls.localize('showEditorTabs', ""Controls if opened editors should show in tabs or not.""), ++ 'default': true ++ }, ++ 'workbench.editor.tabCloseButton': { ++ 'type': 'string', ++ 'enum': ['left', 'right', 'off'], ++ 'default': 'right', ++ 'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, ""Controls the position of the editor's tabs close buttons or disables them when set to 'off'."") ++ }, ++ 'workbench.editor.showIcons': { ++ 'type': 'boolean', ++ 'description': nls.localize('showIcons', ""Controls if opened editors should show with an icon or not. This requires an icon theme to be enabled as well.""), ++ 'default': true ++ }, ++ 'workbench.editor.enablePreview': { ++ 'type': 'boolean', ++ 'description': nls.localize('enablePreview', ""Controls if opened editors show as preview. Preview editors are reused until they are kept (e.g. via double click or editing).""), ++ 'default': true ++ }, ++ 'workbench.editor.enablePreviewFromQuickOpen': { ++ 'type': 'boolean', ++ 'description': nls.localize('enablePreviewFromQuickOpen', ""Controls if opened editors from Quick Open show as preview. Preview editors are reused until they are kept (e.g. via double click or editing).""), ++ 'default': true ++ }, ++ 'workbench.editor.openPositioning': { ++ 'type': 'string', ++ 'enum': ['left', 'right', 'first', 'last'], ++ 'default': 'right', ++ 'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorOpenPositioning' }, ""Controls where editors open. Select 'left' or 'right' to open editors to the left or right of the current active one. Select 'first' or 'last' to open editors independently from the currently active one."") ++ }, ++ 'workbench.editor.revealIfOpen': { ++ 'type': 'boolean', ++ 'description': nls.localize('revealIfOpen', ""Controls if an editor is revealed in any of the visible groups if opened. If disabled, an editor will prefer to open in the currently active editor group. If enabled, an already opened editor will be revealed instead of opened again in the currently active editor group. Note that there are some cases where this setting is ignored, e.g. when forcing an editor to open in a specific group or to the side of the currently active group.""), ++ 'default': false ++ }, ++ 'workbench.quickOpen.closeOnFocusLost': { ++ 'type': 'boolean', ++ 'description': nls.localize('closeOnFocusLost', ""Controls if Quick Open should close automatically once it loses focus.""), ++ 'default': true ++ }, ++ 'workbench.settings.openDefaultSettings': { ++ 'type': 'boolean', ++ 'description': nls.localize('openDefaultSettings', ""Controls if opening settings also opens an editor showing all default settings.""), ++ 'default': true ++ }, ++ 'workbench.sideBar.location': { ++ 'type': 'string', ++ 'enum': ['left', 'right'], ++ 'default': 'left', ++ 'description': nls.localize('sideBarLocation', ""Controls the location of the sidebar. It can either show on the left or right of the workbench."") ++ }, ++ 'workbench.statusBar.visible': { ++ 'type': 'boolean', ++ 'default': true, ++ 'description': nls.localize('statusBarVisibility', ""Controls the visibility of the status bar at the bottom of the workbench."") ++ }, ++ 'workbench.activityBar.visible': { ++ 'type': 'boolean', ++ 'default': true, ++ 'description': nls.localize('activityBarVisibility', ""Controls the visibility of the activity bar in the workbench."") ++ }, ++ 'workbench.editor.closeOnFileDelete': { ++ 'type': 'boolean', ++ 'description': nls.localize('closeOnFileDelete', ""Controls if editors showing a file should close automatically when the file is deleted or renamed by some other process. Disabling this will keep the editor open as dirty on such an event. Note that deleting from within the application will always close the editor and that dirty files will never close to preserve your data.""), ++ 'default': true ++ } ++}; ++ ++if (isMacintosh) { ++ workbenchProperties['workbench.editor.swipeBetweenOpenFiles'] = {","I am not a big fan of the naming `swipeBetweenOpenFiles`, because in reality you can swipe left and right between any editor that is opened, not just files. How about naming this `workbench.editor.swipeToNavigate`?",2017-04-18 05:53:33 +648,"@@ -760,7 +760,7 @@ export class EditorGroupsControl implements IEditorGroupsControl, IVerticalSashL + this.sashTwo.setOrientation(this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL); + + // Trigger layout +- this.arrangeGroups(GroupArrangement.EVEN); ++ this.arrangeGroups(GroupArrangement.KEEP_RATIO);","Suggest to not introduce a `GroupArrangement.KEEP_RATIO` but rather allow to call `arrangeGroups` without any parameter and then use that as an indication to ""keep the ratio"". I would not expose this as API but just set the arrangement optional here in this file.",2017-01-04 10:26:25 +559,"@@ -761,6 +768,8 @@ export class WindowsManager implements IWindowsMainService { + } + } + ++ this.backupService.registerWindowForBackups(vscodeWindow.id, !configuration.workspacePath, configuration.backupFolder, configuration.workspacePath);",@Tyriar are you missing the check for `openConfig.cli.extensionDevelopmentPath` on purpose here?,2016-12-02 06:47:15 +361,"@@ -77,16 +78,22 @@ export class EditorPickerEntry extends QuickOpenEntryGroup { + + public run(mode: Mode, context: IEntryRunContext): boolean { + if (mode === Mode.OPEN) { +- return this.runOpen(context); ++ this.runOpen(context); ++ ++ return true; ++ }","@wprater style: `} else {` +",2016-10-21 09:54:52 +834,"@@ -77,6 +77,7 @@ export interface IExpression extends ITreeElement, IExpressionContainer { + ",Looks good,2017-03-21 17:00:36 +267,"@@ -77,7 +77,7 @@ function prepareDebPackage(arch) { + function buildDebPackage(arch) { + const debArch = getDebPackageArch(arch); + return shell.task([ +- 'chmod 755 ' + product.applicationName + '-' + debArch + '/DEBIAN/postinst ' + product.applicationName + '-' + debArch + '/DEBIAN/prerm', ++ 'chmod 755 ' + product.applicationName + '-' + debArch + '/DEBIAN/postinst ' + product.applicationName + '-' + debArch + '/DEBIAN/prerm ' + product.applicationName + '-' + debArch + '/DEBIAN/postrm',","Thanks for fixing this! +",2016-09-06 16:04:08 +378,"@@ -778,9 +746,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil + this.createTextEditorModelPromise = null; + + this.cancelAutoSavePromises(); +- this.cancelBackupPromises(); + +- this.fileService.discardBackup(this.resource); ++ // TODO: Can this be moved to BackupModelService? ++ this.backupFileService.discardAndDeregisterResource(this.resource);","Yes, I suggest another event on the service maybe when this model gets disposed. +",2016-10-21 14:06:28 +646,"@@ -78,20 +78,32 @@ export class OnEnterSupport { + + // (3): Indentation Support + if (this._indentationRules) { ++ let enterAction: EnterAction = null; + if (this._indentationRules.increaseIndentPattern && this._indentationRules.increaseIndentPattern.test(beforeEnterText)) { +- return OnEnterSupport._INDENT; ++ enterAction = OnEnterSupport._INDENT; + } + if (this._indentationRules.indentNextLinePattern && this._indentationRules.indentNextLinePattern.test(beforeEnterText)) { +- return OnEnterSupport._INDENT; ++ enterAction = OnEnterSupport._INDENT; + } + if (/^\s/.test(beforeEnterText)) { + // No reason to run regular expressions if there is nothing to outdent from + if (this._indentationRules.decreaseIndentPattern && this._indentationRules.decreaseIndentPattern.test(afterEnterText)) { +- return OnEnterSupport._OUTDENT; ++ enterAction = OnEnterSupport._OUTDENT; + } + if (this._indentationRules.indentNextLinePattern && this._indentationRules.indentNextLinePattern.test(oneLineAboveText)) { +- return OnEnterSupport._OUTDENT; ++ enterAction = OnEnterSupport._OUTDENT; + } ++ if (this._indentationRules.decreaseIndentPattern && this._indentationRules.decreaseIndentPattern.test(beforeEnterText)) { ++ if (enterAction === null) { ++ enterAction = { indentAction: IndentAction.None, outdentCurrentLine: true }; ++ } else { ++ enterAction.outdentCurrentLine = true;","Given this line modifies enterAction, please remove the instances OnEnterSupport._INDENT, OnEnterSupport._OUTDENT and create new object instances everywhere, otherwise the second call to this function might contain a stale outdentCurrentLine set to true.",2016-12-27 09:20:58 +860,"@@ -78,7 +78,11 @@ export interface IEditorGroupsControl { + setGroupOrientation(orientation: GroupOrientation): void; + getGroupOrientation(): GroupOrientation; + ++ requestActiveGroupSizeChange(groupSizeChange: number): boolean;","Can we maybe call this similar to the other one `resizePart` in `partService`, e.g. `resizeGroup` and you pass in the position of the group to resize?",2017-03-24 20:25:46 +986,"@@ -785,6 +786,19 @@ export class ImportFileAction extends BaseFileAction { + return this.tree; + } + ++ private bringWindowToForeground(): void { ++ if (isWindows) { ++ try { ++ const { allowSetForegroundWindow } = require.__$__nodeRequire('windows-foreground-love'); ++ allowSetForegroundWindow(process.pid);","Testing this, I do not see any fix for the issue where sometimes the task bar is just flashing and focus is not put. I suggest to remove this code for now, I see no added value.",2017-06-18 15:46:23 +985,"@@ -785,6 +786,19 @@ export class ImportFileAction extends BaseFileAction { + return this.tree; + } + ++ private bringWindowToForeground(): void { ++ if (isWindows) { ++ try { ++ const { allowSetForegroundWindow } = require.__$__nodeRequire('windows-foreground-love'); ++ allowSetForegroundWindow(process.pid); ++ } catch (e) { ++ // noop ++ } ++ } ++ ++ this.windowService.focusWindow();",I suggest to move this closer to the place of the drop operation because that is really where we want to focus the window: https://github.com/Microsoft/vscode/blob/ben/work/src/vs/workbench/parts/files/browser/views/explorerViewer.ts#L735,2017-06-18 15:45:52 +924,"@@ -79,6 +79,27 @@ export class ExtensionTipsService implements IExtensionTipsService { + }, err => []); + } + ++ addToWorkspaceRecommendations(extensionId: string): TPromise {","- Check if extensionId is valid or not +- I would rather use workbench model service and json edit utility to update. This will retain the existing formatting options of the file. Refer [ConfigurationEditingService](https://github.com/microsoft/vscode/blob/thr0w-13456/src/vs/workbench/services/configuration/node/configurationEditingService.ts#L64) that edits configuration files programatically.",2017-05-12 08:56:08 +42,"@@ -79,6 +82,7 @@ export class Workbench implements IPartService { + + private static sidebarPositionSettingKey = 'workbench.sidebar.position'; + private static sidebarHiddenSettingKey = 'workbench.sidebar.hidden'; ++ private static panelPartHiddenSettingKey = 'workbench.panelPart.hidden';","@isidorn suggest to call it just ""workbench.panel.hidden"" +",2016-01-15 15:17:23 +925,"@@ -799,6 +799,32 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { + }); + } + ++ addToWorkspaceRecommendations(extension: IExtension): TPromise { ++ return this.tipsService.addToWorkspaceRecommendations(extension.id); ++ } ++ ++ installAllWorkspaceRecommendations(): TPromise { ++ return this.tipsService.getWorkspaceRecommendations() ++ .then(extensions => { ++ this.queryGallery({ names: extensions }) ++ .done(result => { ++ if (result.total < 1) { ++ return; ++ } ++ ++ const extension = result.firstPage[0]; ++ const promises = [this.open(extension)];",Sorry.. I did not get why do we need to open extension,2017-05-12 08:59:10 +926,"@@ -799,6 +799,32 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { + }); + } + ++ addToWorkspaceRecommendations(extension: IExtension): TPromise { ++ return this.tipsService.addToWorkspaceRecommendations(extension.id); ++ } ++ ++ installAllWorkspaceRecommendations(): TPromise { ++ return this.tipsService.getWorkspaceRecommendations() ++ .then(extensions => { ++ this.queryGallery({ names: extensions }) ++ .done(result => { ++ if (result.total < 1) { ++ return; ++ } ++ ++ const extension = result.firstPage[0]; ++ const promises = [this.open(extension)]; ++ ++ if (this.local.every(local => local.id !== extension.id)) { ++ promises.push(this.install(extension)); ++ } ++",Not sure if I misunderstood.. I see it is installing only one recommended extensions in the list not all.. I do not see complete result is being read to install?,2017-05-12 09:02:45 +727,"@@ -8,11 +8,115 @@ import * as strings from 'vs/base/common/strings'; + import { IState, ITokenizationSupport, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes'; + import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode'; + import { LineTokens } from 'vs/editor/common/core/lineTokens'; ++import { CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer'; ++import { CharCode } from 'vs/base/common/charCode'; ++import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; + + export function tokenizeToString(text: string, languageId: string): string { + return _tokenizeToString(text, _getSafeTokenizationSupport(languageId)); + } + ++export function tokenizeLineToHTML(text: string, viewLineTokens: ViewLineToken[], rules: { [key: string]: string }, options: { startOffset: number, endOffset: number, tabSize: number, containsRTL: boolean }): string { ++ let tabSize = options.tabSize; ++ let containsRTL = options.containsRTL; ++ ++ let result = `
`; ++ const characterMapping = new CharacterMapping(text.length + 1, viewLineTokens.length);",No need to build up character mapping here,2017-02-16 15:48:36 +729,"@@ -8,11 +8,115 @@ import * as strings from 'vs/base/common/strings'; + import { IState, ITokenizationSupport, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes'; + import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode'; + import { LineTokens } from 'vs/editor/common/core/lineTokens'; ++import { CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer'; ++import { CharCode } from 'vs/base/common/charCode'; ++import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; + + export function tokenizeToString(text: string, languageId: string): string { + return _tokenizeToString(text, _getSafeTokenizationSupport(languageId)); + } + ++export function tokenizeLineToHTML(text: string, viewLineTokens: ViewLineToken[], rules: { [key: string]: string }, options: { startOffset: number, endOffset: number, tabSize: number, containsRTL: boolean }): string { ++ let tabSize = options.tabSize; ++ let containsRTL = options.containsRTL; ++ ++ let result = `
`; ++ const characterMapping = new CharacterMapping(text.length + 1, viewLineTokens.length); ++ ++ let charIndex = options.startOffset; ++ let tabsCharDelta = 0; ++ let charOffsetInPart = 0;","since there's no need to build up character mapping, there's also no need to keep track of charOffsetInPart",2017-02-16 15:50:33 +728,"@@ -8,11 +8,115 @@ import * as strings from 'vs/base/common/strings'; + import { IState, ITokenizationSupport, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes'; + import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode'; + import { LineTokens } from 'vs/editor/common/core/lineTokens'; ++import { CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer'; ++import { CharCode } from 'vs/base/common/charCode'; ++import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; + + export function tokenizeToString(text: string, languageId: string): string { + return _tokenizeToString(text, _getSafeTokenizationSupport(languageId)); + } + ++export function tokenizeLineToHTML(text: string, viewLineTokens: ViewLineToken[], rules: { [key: string]: string }, options: { startOffset: number, endOffset: number, tabSize: number, containsRTL: boolean }): string { ++ let tabSize = options.tabSize; ++ let containsRTL = options.containsRTL; ++ ++ let result = `
`; ++ const characterMapping = new CharacterMapping(text.length + 1, viewLineTokens.length); ++ ++ let charIndex = options.startOffset; ++ let tabsCharDelta = 0; ++ let charOffsetInPart = 0; ++ ++ for (let tokenIndex = 0, lenJ = viewLineTokens.length; tokenIndex < lenJ; tokenIndex++) { ++ const token = viewLineTokens[tokenIndex]; ++ const tokenEndIndex = token.endIndex; ++ ++ if (token.endIndex < options.startOffset) { ++ continue; ++ } ++ ++ const tokenType = token.type; ++ let partContentCnt = 0;","since there's no need to build up character mapping, there's also no need to keep track of partContentCnt",2017-02-16 15:49:59 +730,"@@ -8,11 +8,115 @@ import * as strings from 'vs/base/common/strings'; + import { IState, ITokenizationSupport, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes'; + import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode'; + import { LineTokens } from 'vs/editor/common/core/lineTokens'; ++import { CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer'; ++import { CharCode } from 'vs/base/common/charCode'; ++import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; + + export function tokenizeToString(text: string, languageId: string): string { + return _tokenizeToString(text, _getSafeTokenizationSupport(languageId)); + } + ++export function tokenizeLineToHTML(text: string, viewLineTokens: ViewLineToken[], rules: { [key: string]: string }, options: { startOffset: number, endOffset: number, tabSize: number, containsRTL: boolean }): string { ++ let tabSize = options.tabSize; ++ let containsRTL = options.containsRTL; ++ ++ let result = `
`; ++ const characterMapping = new CharacterMapping(text.length + 1, viewLineTokens.length); ++ ++ let charIndex = options.startOffset; ++ let tabsCharDelta = 0; ++ let charOffsetInPart = 0; ++ ++ for (let tokenIndex = 0, lenJ = viewLineTokens.length; tokenIndex < lenJ; tokenIndex++) { ++ const token = viewLineTokens[tokenIndex]; ++ const tokenEndIndex = token.endIndex; ++ ++ if (token.endIndex < options.startOffset) { ++ continue; ++ } ++ ++ const tokenType = token.type; ++ let partContentCnt = 0; ++ let partContent = ''; ++ ++ for (; charIndex < tokenEndIndex && charIndex < options.endOffset; charIndex++) { ++ characterMapping.setPartData(charIndex, tokenIndex, charOffsetInPart); ++ const charCode = text.charCodeAt(charIndex); ++ ++ switch (charCode) { ++ case CharCode.Tab: ++ let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize; ++ tabsCharDelta += insertSpacesCount - 1; ++ charOffsetInPart += insertSpacesCount - 1; ++ while (insertSpacesCount > 0) { ++ partContent += ' '; ++ partContentCnt++; ++ insertSpacesCount--; ++ } ++ break; ++ ++ case CharCode.Space: ++ partContent += ' '; ++ partContentCnt++; ++ break; ++ ++ case CharCode.LessThan: ++ partContent += '<'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.GreaterThan: ++ partContent += '>'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.Ampersand: ++ partContent += '&'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.Null: ++ partContent += '�'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.UTF8_BOM: ++ case CharCode.LINE_SEPARATOR_2028: ++ partContent += '\ufffd'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.CarriageReturn: ++ // zero width space, because carriage return would introduce a line break ++ partContent += '​'; ++ partContentCnt++; ++ break; ++ ++ default: ++ partContent += String.fromCharCode(charCode); ++ partContentCnt++; ++ } ++ ++ charOffsetInPart++; ++ } ++ ++ characterMapping.setPartLength(tokenIndex, partContentCnt); ++ let style = tokenType.split(' ').map(type => rules[type]).join('');","please leave a todo here, we should clean this up once I merge the minimap branch where a view line token holds on to the metadata, it should be straight-forward with those changes to read here the font style and the foreground color directly",2017-02-16 15:52:49 +731,"@@ -8,11 +8,115 @@ import * as strings from 'vs/base/common/strings'; + import { IState, ITokenizationSupport, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes'; + import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode'; + import { LineTokens } from 'vs/editor/common/core/lineTokens'; ++import { CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer'; ++import { CharCode } from 'vs/base/common/charCode'; ++import { ViewLineToken } from 'vs/editor/common/core/viewLineToken'; + + export function tokenizeToString(text: string, languageId: string): string { + return _tokenizeToString(text, _getSafeTokenizationSupport(languageId)); + } + ++export function tokenizeLineToHTML(text: string, viewLineTokens: ViewLineToken[], rules: { [key: string]: string }, options: { startOffset: number, endOffset: number, tabSize: number, containsRTL: boolean }): string { ++ let tabSize = options.tabSize; ++ let containsRTL = options.containsRTL; ++ ++ let result = `
`; ++ const characterMapping = new CharacterMapping(text.length + 1, viewLineTokens.length); ++ ++ let charIndex = options.startOffset; ++ let tabsCharDelta = 0; ++ let charOffsetInPart = 0; ++ ++ for (let tokenIndex = 0, lenJ = viewLineTokens.length; tokenIndex < lenJ; tokenIndex++) { ++ const token = viewLineTokens[tokenIndex]; ++ const tokenEndIndex = token.endIndex; ++ ++ if (token.endIndex < options.startOffset) { ++ continue; ++ } ++ ++ const tokenType = token.type; ++ let partContentCnt = 0; ++ let partContent = ''; ++ ++ for (; charIndex < tokenEndIndex && charIndex < options.endOffset; charIndex++) { ++ characterMapping.setPartData(charIndex, tokenIndex, charOffsetInPart); ++ const charCode = text.charCodeAt(charIndex); ++ ++ switch (charCode) { ++ case CharCode.Tab: ++ let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize; ++ tabsCharDelta += insertSpacesCount - 1; ++ charOffsetInPart += insertSpacesCount - 1; ++ while (insertSpacesCount > 0) { ++ partContent += ' '; ++ partContentCnt++; ++ insertSpacesCount--; ++ } ++ break; ++ ++ case CharCode.Space: ++ partContent += ' '; ++ partContentCnt++; ++ break; ++ ++ case CharCode.LessThan: ++ partContent += '<'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.GreaterThan: ++ partContent += '>'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.Ampersand: ++ partContent += '&'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.Null: ++ partContent += '�'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.UTF8_BOM: ++ case CharCode.LINE_SEPARATOR_2028: ++ partContent += '\ufffd'; ++ partContentCnt++; ++ break; ++ ++ case CharCode.CarriageReturn: ++ // zero width space, because carriage return would introduce a line break ++ partContent += '​'; ++ partContentCnt++; ++ break; ++ ++ default: ++ partContent += String.fromCharCode(charCode); ++ partContentCnt++; ++ } ++ ++ charOffsetInPart++; ++ } ++ ++ characterMapping.setPartLength(tokenIndex, partContentCnt); ++ let style = tokenType.split(' ').map(type => rules[type]).join(''); ++ if (containsRTL) { ++ result += `${partContent}`;","perhaps this is overkill. I have a feeling the software where we paste should figure out by itself what to do with RTL characters, so I suggest to ignore RTL here for now.",2017-02-16 15:53:59 +81,"@@ -8,11 +8,16 @@ + bash + zsh + bashrc ++ zshrc","I think you can safely remove these since they're added to the package.json which is the source of truth. Good to go after this is done :+1: +",2016-03-22 08:10:18 +9,"@@ -8,13 +8,13 @@ define([ + ""vs/languages/html/common/html.contribution"", + ""vs/languages/javascript/common/javascript.contribution"", + ""vs/languages/json/common/json.contribution"", ++ ""vs/languages/less/common/less.contribution"", + ""vs/languages/markdown/common/markdown.contribution"", + ""vs/languages/php/common/php.contribution"", + ""vs/languages/plaintext/common/plaintext.contribution"", + ""vs/languages/razor/common/razor.contribution"", +- ""vs/languages/typescript/common/typescript.contribution"", +- ""vs/languages/less/common/less.contribution"", +- ""vs/languages/sass/common/sass.contribution"" ++ ""vs/languages/sass/common/sass.contribution"", ++ ""vs/languages/typescript/common/typescript.contribution""","This change is not really necessary +",2015-11-21 19:12:58 +757,"@@ -8,14 +8,12 @@ + background-image: url('debug.svg'); + } + +-.monaco-editor .debug-top-stack-frame-line { ++.monaco-editor .debug-top-stack-frame-line, ++.monaco-editor .debug-top-stack-frame-exception-line ++{",Put the bracket on the previous line,2017-02-20 14:17:29 +499,"@@ -8,23 +8,22 @@ import { TPromise } from 'vs/base/common/winjs.base'; + import URI from 'vs/base/common/uri'; + import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + import { IModel } from 'vs/editor/common/editorCommon'; +-import { ITextEditorModel as IBaseTextEditorModel } from 'vs/platform/editor/common/editor'; +-import { IDisposable } from 'vs/base/common/lifecycle'; ++import { IEditorModel } from 'vs/platform/editor/common/editor'; ++import { IDisposable, IReference } from 'vs/base/common/lifecycle'; + + export const ITextModelResolverService = createDecorator('textModelResolverService'); + + export interface ITextModelResolverService { + _serviceBrand: any; + + /** +- * Given a resource, tries to resolve a ITextEditorModel out of it. Will support many schemes like file://, untitled://, +- * inMemory:// and for anything else fall back to the model content provider registry. ++ * Provided a resource URI, it will return a model reference ++ * which should be disposed once not needed anymore. + */ +- resolve(resource: URI): TPromise; ++ getModelReference(resource: URI): IReference>;","@joaomoreno good stuff. the only thing I am uncertain about is the flow of getting the reference and disposing it. Typically we say you need to `dispose` if you called a `create` method. Here we do a `getReference` and then ask clients to `dispose`. + +I think I would also call it `aquire` and `release` in the resolver service so that it becomes clear that you need to dispose. I am also fine with `createReference` and `dispose`. ",2016-11-21 12:55:56 +451,"@@ -8,6 +8,7 @@ + import 'vs/css!./media/activitybarpart'; + import nls = require('vs/nls'); + import { TPromise } from 'vs/base/common/winjs.base'; ++import Event, { Emitter } from 'vs/base/common/event';","@octref I expect some code from here to move out to `IViewletService` or `IExtensionViewletService`. it feels lots of things that should not be activity bar related are now inside this part. To me, the part should not really distinguish between normal viewlets and extension viewlets, but just do its business of rendering a set of viewlets and their activity. +",2016-11-03 08:49:44 +686,"@@ -8,6 +8,7 @@ import * as paths from 'vs/base/common/paths'; + import * as platform from 'vs/base/common/platform'; + import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; + import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; ++import debug = require('vs/workbench/parts/debug/common/debug'); + ","This is the old style of importing we no longer use, instead we should switch to +`import * as debug from 'vs/workbench/parts/debug/common/debug'` +which should be preferable in new TS versions",2017-01-18 14:08:56 +658,"@@ -8,6 +8,7 @@ import { isLinux, isWindows } from 'vs/base/common/platform'; + import { fill } from 'vs/base/common/arrays'; + import { rtrim } from 'vs/base/common/strings'; + import { CharCode } from 'vs/base/common/charCode'; ++import { endsWith } from 'vs/base/common/strings';",@hun1ahpu unused import?,2017-01-10 05:44:32 +513,"@@ -80,6 +80,7 @@ export class TerminalService implements ITerminalService { + this.setActiveInstanceByIndex(0); + } + this._onInstancesChanged.fire(); ++ terminalInstance.setCommandsToSkipShell(this.configHelper.getCommandsToSkipShell());","You've actually stumbled upon a bug bigger than this in that no settings values are updated correctly, including scrollback and cursorBlinking as well. Having a brief look at the code, I think the best way to fix this might be to move `TerminalPanel._updateConfig` to `TerminalService.updateConfig` and then call into that after creating the new instance.",2016-11-24 21:09:19 +997,"@@ -80,6 +83,11 @@ export function isWelcomePageEnabled(storageService: IStorageService) { + return 'enableWelcomePage' in overrides ? overrides.enableWelcomePage : splitExperimentsRandomness(storageService).enableWelcomePage; + } + ++export function isShowTaskDocumentation(storageService: IStorageService) {",This is not needed then (see below). The welcome page one (you probably looked at) was a special case I'm about to remove.,2017-06-19 22:01:32 +525,"@@ -80,6 +83,9 @@ export class TerminalService implements ITerminalService { + this.setActiveInstanceByIndex(0); + } + this._onInstancesChanged.fire(); ++ this._updateCursorBlink(terminalInstance);","These calls would be more at home inside `TerminalInstance.constructor`. Thinking about this further we may be able to get rid of both calls in `TerminalPanel.setVisible` as well by updating the config at the end of `TerminalInstance.attachToElement`. I believe that covers the cases we need to worry about for updating the config: + +- When the terminal is created and the panel exists (`attachToElement` will trigger immediately) +- When the terminal is created via the API and the panel does not exist (`attachToElement` call will be deferred) +- When the config is updated (`TerminalService` now listens to `IConfigurationservice.onDidUpdateConfiguration`)",2016-11-28 19:09:11 +815,"@@ -808,9 +808,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService + this._onEditorsMoved.fire(); + } + +- public moveEditor(input: EditorInput, from: EditorGroup, to: EditorGroup, index?: number): void; +- public moveEditor(input: EditorInput, from: Position, to: Position, index?: number): void; +- public moveEditor(input: EditorInput, arg2: any, arg3: any, index?: number): void { ++ public moveEditor(input: EditorInput, from: EditorGroup, to: EditorGroup, index?: number, inactive?: boolean): void;",I suggest to put `index` and `inactive` into a new optional options bag (`IMoveOptions`).,2017-03-11 07:14:11 +29,"@@ -81,22 +83,37 @@ export class PluginScanner { + /** + * Scan a list of extensions defined in `absoluteFolderPath` + */ +- public static scanPlugins(version: string, collector: IPluginsMessageCollector, absoluteFolderPath:string, isBuiltin:boolean): TPromise { +- return pfs.readDirsInDir(absoluteFolderPath).then((folders) => { +- return TPromise.join( +- folders.map((folder) => this.scanPlugin(version, collector, paths.join(absoluteFolderPath, folder), isBuiltin)) +- ); +- }, (err) => { +- collector.error(absoluteFolderPath, err); +- return []; +- }).then((results) => results.filter(item => (item !== null))); ++ public static scanPlugins( ++ version: string, ++ collector: IPluginsMessageCollector, ++ absoluteFolderPath:string, ++ isBuiltin:boolean ++ ) : TPromise ++ { ++ return pfs.readDirsInDir(absoluteFolderPath) ++ .then(folders => TPromise.join(folders.map(f => this.scanPlugin(version, collector, paths.join(absoluteFolderPath, f), isBuiltin)))) ++ .then(plugins => plugins.filter(item => item !== null)) ++ .then(plugins => { ++ const pluginsById = values(groupBy(plugins, p => p.id)); ++ return pluginsById.map(p => p.sort((a, b) => semver.rcompare(a.version, b.version))[0]);","@joaomoreno + +`semver.rcompare(a.version, b.version)` throws if `a.version` or `b.version` are undefined. + +Effectively, this change makes `version` a required field in `package.json`. If this is the intent, then the validation of `package.json` must reflect this. If the version field is required, then `pluginsRegistry.ts` > `isValidPluginDescription` must be updated to check the field exists and **is parsable by semver**. + +The following `package.json` breaks all user extension loading: + +``` +{ + ""name"": ""test"", + ""publisher"": ""alex"", + ""engines"": { + ""vscode"": ""0.10.x"" + } +} +``` + +Just place it twice in the extensions folder with two different folder names to repro. It should fail twice but not prevent other extensions in the same folder from being discovered. + +You can do the following: +- in `pluginsRegistry.ts` > `isValidPluginDescription` check that a version field is present and is a string +- in `vs\platform\plugins\node\pluginVersionValidator.ts` > `isValidPluginDescription` use semver and check that semver can parse the version + +Of course all of this if you know for a fact that no extension made it into the gallery without a valid semver version field, otherwise this new check might break already installed extensions +",2015-12-16 14:12:08 +472,"@@ -81,7 +81,7 @@ export class FileService implements IFileService { + + // create service + const workspace = this.contextService.getWorkspace(); +- this.raw = new NodeFileService(workspace ? workspace.resource.fsPath : void 0, fileServiceConfig, this.eventService); ++ this.raw = new NodeFileService(workspace ? workspace.resource.fsPath : void 0, fileServiceConfig, this.eventService, this.environmentService, this.configurationService);","@Tyriar these changes are all NOT needed +",2016-11-09 07:40:51 +841,"@@ -82,23 +94,31 @@ class EditTask implements IDisposable { + } + + public addEdit(edit: IResourceEdit): void { +- let range: IRange; +- if (!edit.range) { +- range = this._model.getFullModelRange(); ++ if (isIEndOfLineSequenceEdit(edit)) { ++ // store new EOL-sequence, last wins ++ this._newEol = edit.eol; ++ + } else { +- range = edit.range; ++ // create edit operation ++ let range: IRange;","Consider a `const` here: +```ts +const range = edit.range || this._model.getFullModelRange(); +```",2017-03-21 17:44:01 +164,"@@ -83,18 +100,60 @@ export class TerminalConfigHelper { + return DEFAULT_ANSI_COLORS[baseThemeId]; + } + ++ private initializeCharacterSize(font: ITerminalFont, parentDomElement: HTMLElement) { ++ if (!this.characterMeasureElement) { ++ this.characterMeasureElement = new Builder(parentDomElement, true).div().build().getHTMLElement(); ++ } ++ ++ this.characterMeasureElement.style.display = 'inline'; ++ this.characterMeasureElement.style.fontFamily = font.fontFamily; ++ this.characterMeasureElement.style.fontSize = font.fontSize + 'px'; ++ this.characterMeasureElement.style.lineHeight = font.lineHeight + 'px'; ++ this.characterMeasureElement.innerText = 'X'; ++ let bcr = this.characterMeasureElement.getBoundingClientRect();","Probably better named `rect` +",2016-06-02 06:48:36 +165,"@@ -83,18 +100,60 @@ export class TerminalConfigHelper { + return DEFAULT_ANSI_COLORS[baseThemeId]; + } + ++ private initializeCharacterSize(font: ITerminalFont, parentDomElement: HTMLElement) { ++ if (!this.characterMeasureElement) { ++ this.characterMeasureElement = new Builder(parentDomElement, true).div().build().getHTMLElement(); ++ } ++ ++ this.characterMeasureElement.style.display = 'inline'; ++ this.characterMeasureElement.style.fontFamily = font.fontFamily; ++ this.characterMeasureElement.style.fontSize = font.fontSize + 'px'; ++ this.characterMeasureElement.style.lineHeight = font.lineHeight + 'px'; ++ this.characterMeasureElement.innerText = 'X'; ++ let bcr = this.characterMeasureElement.getBoundingClientRect(); ++ this.characterMeasureElement.style.display = 'none'; ++ this.charWidth = Math.ceil(bcr.width || TERMINAL_CHAR_WIDTH_FALLBACK);","Do you know when `bcr.width` will be falsey or was this just defensive? +",2016-06-02 06:51:25 +166,"@@ -83,18 +100,60 @@ export class TerminalConfigHelper { + return DEFAULT_ANSI_COLORS[baseThemeId]; + } + ++ private initializeCharacterSize(font: ITerminalFont, parentDomElement: HTMLElement) { ++ if (!this.characterMeasureElement) { ++ this.characterMeasureElement = new Builder(parentDomElement, true).div().build().getHTMLElement(); ++ } ++ ++ this.characterMeasureElement.style.display = 'inline'; ++ this.characterMeasureElement.style.fontFamily = font.fontFamily; ++ this.characterMeasureElement.style.fontSize = font.fontSize + 'px'; ++ this.characterMeasureElement.style.lineHeight = font.lineHeight + 'px'; ++ this.characterMeasureElement.innerText = 'X'; ++ let bcr = this.characterMeasureElement.getBoundingClientRect(); ++ this.characterMeasureElement.style.display = 'none'; ++ this.charWidth = Math.ceil(bcr.width || TERMINAL_CHAR_WIDTH_FALLBACK); ++ this.charHeight = Math.ceil(bcr.height || TERMINAL_CHAR_HEIGHT_FALLBACK); ++ } ++ + /** +- * Set the terminal font to `terminal.integrated.fontFamily` if it is set, otherwise fallback to +- * `editor.fontFamily`. ++ * Gets the font information based on the terminal.integrated.fontFamily, ++ * terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties ++ * ++ * @param parentDomElement Host for the character measurement element ++ * @param updateCharSize A flag which indicates whether the character size should be measured + */ +- public getFontFamily(): string { ++ public getFont(parentDomElement: HTMLElement, updateCharSize?: boolean): ITerminalFont {","Pass `parentDomElement` into the constructor and have `TerminalConfigHelper` keep a pointer to it. +",2016-06-02 06:52:58 +168,"@@ -83,18 +100,60 @@ export class TerminalConfigHelper { + return DEFAULT_ANSI_COLORS[baseThemeId]; + } + ++ private initializeCharacterSize(font: ITerminalFont, parentDomElement: HTMLElement) { ++ if (!this.characterMeasureElement) { ++ this.characterMeasureElement = new Builder(parentDomElement, true).div().build().getHTMLElement(); ++ } ++ ++ this.characterMeasureElement.style.display = 'inline'; ++ this.characterMeasureElement.style.fontFamily = font.fontFamily; ++ this.characterMeasureElement.style.fontSize = font.fontSize + 'px'; ++ this.characterMeasureElement.style.lineHeight = font.lineHeight + 'px'; ++ this.characterMeasureElement.innerText = 'X'; ++ let bcr = this.characterMeasureElement.getBoundingClientRect(); ++ this.characterMeasureElement.style.display = 'none'; ++ this.charWidth = Math.ceil(bcr.width || TERMINAL_CHAR_WIDTH_FALLBACK); ++ this.charHeight = Math.ceil(bcr.height || TERMINAL_CHAR_HEIGHT_FALLBACK); ++ } ++ + /** +- * Set the terminal font to `terminal.integrated.fontFamily` if it is set, otherwise fallback to +- * `editor.fontFamily`. ++ * Gets the font information based on the terminal.integrated.fontFamily, ++ * terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties ++ * ++ * @param parentDomElement Host for the character measurement element ++ * @param updateCharSize A flag which indicates whether the character size should be measured + */ +- public getFontFamily(): string { ++ public getFont(parentDomElement: HTMLElement, updateCharSize?: boolean): ITerminalFont { + let terminalConfig = this.configurationService.getConfiguration(); ++ let editorConfig = this.configurationService.getConfiguration(); ++ + let fontFamily = terminalConfig.terminal.integrated.fontFamily; ++ let fontSize = this.toInteger(terminalConfig.terminal.integrated.fontSize, 0, 100) || this.toInteger(editorConfig.editor.fontSize, 0, 100);","Is the max necessary? + +Also you can simplify: + +``` ts +this.toInteger(terminalConfig.terminal.integrated.fontSize || editorConfig.editor.fontSize, 0, 100) +``` +",2016-06-02 06:57:51 +167,"@@ -83,18 +100,60 @@ export class TerminalConfigHelper { + return DEFAULT_ANSI_COLORS[baseThemeId]; + } + ++ private initializeCharacterSize(font: ITerminalFont, parentDomElement: HTMLElement) { ++ if (!this.characterMeasureElement) { ++ this.characterMeasureElement = new Builder(parentDomElement, true).div().build().getHTMLElement(); ++ } ++ ++ this.characterMeasureElement.style.display = 'inline'; ++ this.characterMeasureElement.style.fontFamily = font.fontFamily; ++ this.characterMeasureElement.style.fontSize = font.fontSize + 'px'; ++ this.characterMeasureElement.style.lineHeight = font.lineHeight + 'px'; ++ this.characterMeasureElement.innerText = 'X'; ++ let bcr = this.characterMeasureElement.getBoundingClientRect(); ++ this.characterMeasureElement.style.display = 'none'; ++ this.charWidth = Math.ceil(bcr.width || TERMINAL_CHAR_WIDTH_FALLBACK); ++ this.charHeight = Math.ceil(bcr.height || TERMINAL_CHAR_HEIGHT_FALLBACK); ++ } ++ + /** +- * Set the terminal font to `terminal.integrated.fontFamily` if it is set, otherwise fallback to +- * `editor.fontFamily`. ++ * Gets the font information based on the terminal.integrated.fontFamily, ++ * terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties ++ * ++ * @param parentDomElement Host for the character measurement element ++ * @param updateCharSize A flag which indicates whether the character size should be measured + */ +- public getFontFamily(): string { ++ public getFont(parentDomElement: HTMLElement, updateCharSize?: boolean): ITerminalFont { + let terminalConfig = this.configurationService.getConfiguration(); ++ let editorConfig = this.configurationService.getConfiguration(); ++ + let fontFamily = terminalConfig.terminal.integrated.fontFamily; ++ let fontSize = this.toInteger(terminalConfig.terminal.integrated.fontSize, 0, 100) || this.toInteger(editorConfig.editor.fontSize, 0, 100); ++ let lineHeight = this.toInteger(terminalConfig.terminal.integrated.lineHeight, 0, 150) || this.toInteger(editorConfig.editor.lineHeight, 0, 150); ++ + if (!fontFamily) { +- let editorConfig = this.configurationService.getConfiguration(); + fontFamily = editorConfig.editor.fontFamily; + } +- return fontFamily; ++ ++ if (lineHeight === 0) { ++ lineHeight = Math.round(GOLDEN_LINE_HEIGHT_RATIO * fontSize); ++ } ++ ++ var font: ITerminalFont = {","Prefer `let` +",2016-06-02 06:55:32 +524,"@@ -84,12 +85,14 @@ export class TerminalPanel extends Panel { + public setVisible(visible: boolean): TPromise { + if (visible) { + if (this._terminalService.terminalInstances.length > 0) { +- this._updateConfig(); ++ this._terminalService.updateConfig(); ++ this._updateFont(); + this._updateTheme(); + } else { + return super.setVisible(visible).then(() => { + this._terminalService.createInstance(); +- this._updateConfig(); ++ this._terminalService.updateConfig();",This shouldn't be needed anymore as it's called within `ITerminalService.createInstance`,2016-11-28 19:02:15 +407,"@@ -84,43 +140,77 @@ export class ActivitybarPart extends Part implements IActivityService { + const $result = $('.content').appendTo($el); + + // Top Actionbar with action items for each viewlet action +- this.createViewletSwitcher($result.clone()); ++ this.createViewletSwitcher($result.clone().addClass('position-top'));","What does this do? +",2016-10-24 15:42:28 +408,"@@ -84,43 +140,77 @@ export class ActivitybarPart extends Part implements IActivityService { + const $result = $('.content').appendTo($el); + + // Top Actionbar with action items for each viewlet action +- this.createViewletSwitcher($result.clone()); ++ this.createViewletSwitcher($result.clone().addClass('position-top')); + + return $result; + } + + private createViewletSwitcher(div: Builder): void { +- +- // Composite switcher is on top","Why remove? +",2016-10-24 15:43:08 +560,"@@ -84,6 +84,7 @@ export interface IWindowConfiguration extends ParsedArgs { + perfWindowLoadTime?: number; + + workspacePath?: string; ++ backupFolder?: string;",@Tyriar suggest `backupPath` to keep naming consistent,2016-12-02 06:48:36 +955,"@@ -84,6 +90,12 @@ export class MergeConflictParser { + return null; + } + ++ let tokenAfterCurrentBlock: vscode.TextLine = scanned.splitter; ++ ++ if (scanned.commonAncestors !== null) { ++ tokenAfterCurrentBlock = scanned.commonAncestors; ++ } ++","Nit; Could be condensed to + +```javascript +const tokenAfterCurrentBlock = scanned.commonAncestors || scanned.splitter; +```",2017-05-30 15:43:48 +638,"@@ -85,4 +85,16 @@ declare module 'vscode' { + */ + getClickCommand?(node: T): string; + } ++ export interface TextEditor { ++ /** ++ * Inserts the given snippet template and enters snippet mode. ++ * ++ * If the editor is already in snippet mode, insertion fails and the returned promise resolves to false. ++ * ++ * @param template The snippet template to insert ++ * @param posOrRange The position or replacement range representing the location of the insertion. ++ * @return A promise that resolves with a value indicating if the snippet could be inserted. ++ */ ++ insertSnippet(template: string, posOrRange: Position | Range): Thenable; ++ }",this isn't needed as we make the change directly in `vscode.d.ts`,2016-12-21 08:17:27 +869,"@@ -85,6 +299,26 @@ const iso639_3_to_2: Map = { + 'trk': 'tr' + }; + ++const iso639_2_to_3: Map = {",We might want to consider using 2 letter id in the future. The reason why we have this mapping is that MS internally uses 3. If all is public we could switch over to 2.,2017-04-04 13:02:52 +664,"@@ -85,6 +85,39 @@ class MyCompletionItem extends CompletionItem { + + return CompletionItemKind.Property; + } ++ ++ private static getCommitCharacters(document: TextDocument, kind: string): string[] | undefined { ++ switch (kind) { ++ case PConst.Kind.externalModuleName: ++ return ['""', '\'']; ++ ++ case PConst.Kind.file: ++ case PConst.Kind.directory: ++ return ['/', '""', '\''];",backslash?,2017-01-12 08:36:26 +665,"@@ -85,6 +85,39 @@ class MyCompletionItem extends CompletionItem { + + return CompletionItemKind.Property; + } ++ ++ private static getCommitCharacters(document: TextDocument, kind: string): string[] | undefined { ++ switch (kind) { ++ case PConst.Kind.externalModuleName: ++ return ['""', '\'']; ++ ++ case PConst.Kind.file: ++ case PConst.Kind.directory: ++ return ['/', '""', '\'']; ++ ++ case PConst.Kind.alias: ++ case PConst.Kind.variable: ++ case PConst.Kind.localVariable: ++ case PConst.Kind.memberVariable: ++ case PConst.Kind.memberGetAccessor: ++ case PConst.Kind.memberSetAccessor: ++ case PConst.Kind.constructSignature: ++ case PConst.Kind.callSignature: ++ case PConst.Kind.indexSignature: ++ case PConst.Kind.enum: ++ case PConst.Kind.module: ++ case PConst.Kind.class: ++ case PConst.Kind.interface: ++ case PConst.Kind.function:",`(` for functions?,2017-01-12 08:36:49 +953,"@@ -85,6 +90,11 @@ export default class MergeDectorator implements vscode.Disposable { + } + }); + ++ this.decorations['commonAncestors.header'] = vscode.window.createTextEditorDecorationType({ ++ color: new vscode.ThemeColor('editor.foreground'),","@kieferrm, @chrmarti: We should probably add a new theme color from common ancestor blocks. I'd be in favor of coloring them at some point. ",2017-05-30 15:41:11 +355,"@@ -85,6 +91,7 @@ export interface IExtensionContributions { + menus?: { [context: string]: IMenu[] }; + snippets?: ISnippet[]; + themes?: ITheme[]; ++ explorer?: ITreeExplorer;","Only one tree per extension? +",2016-10-21 07:44:44 +269,"@@ -85,8 +87,8 @@ export class ExtHostTerminalService { + this._proxy = threadService.get(MainContext.MainThreadTerminalService); + } + +- public createTerminal(name?: string): vscode.Terminal { +- return new ExtHostTerminal(this._proxy, -1, name); ++ public createTerminal(name?: string, path?: string): vscode.Terminal {","path -> shellPath +",2016-09-08 19:02:55 +862,"@@ -853,6 +857,83 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro + return ratio; + } + ++ // Request size change on the active editor/group - changes main axis ++ public requestActiveGroupSizeChange(groupSizeChange: number): boolean { ++ ++ enum VISIBLE_EDITORS { ++ ONE = 1, ++ TWO = 2, ++ THREE = 3 ++ } ++ ++ const visibleEditors = this.getVisibleEditorCount(); ++ ++ if (visibleEditors <= VISIBLE_EDITORS.ONE) { ++ return false; ++ } ++ ++ let availableSize = this.totalSize; ++ const activeGroupPosition = this.getActivePosition(); ++ ++ switch (visibleEditors) { ++ case VISIBLE_EDITORS.TWO: ++ switch (activeGroupPosition) { ++ case Position.ONE: ++ this.silosSize[Position.ONE] = this.boundSiloSize(Position.ONE, groupSizeChange); ++ this.silosSize[Position.TWO] = availableSize - this.silosSize[Position.ONE]; ++ break; ++ case Position.TWO: ++ this.silosSize[Position.TWO] = this.boundSiloSize(Position.TWO, groupSizeChange); ++ this.silosSize[Position.ONE] = availableSize - this.silosSize[Position.TWO]; ++ default: ++ break; ++ } ++ break; ++ case VISIBLE_EDITORS.THREE: ++ switch (activeGroupPosition) { ++ case Position.ONE: ++ this.silosSize[Position.ONE] = this.boundSiloSize(Position.ONE, groupSizeChange); ++ this.distributeRemainingSilosSize(Position.TWO, Position.THREE, availableSize - this.silosSize[Position.ONE]); ++ break; ++ case Position.TWO: ++ this.silosSize[Position.TWO] = this.boundSiloSize(Position.TWO, groupSizeChange); ++ this.distributeRemainingSilosSize(Position.ONE, Position.THREE, availableSize - this.silosSize[Position.TWO]); ++ break; ++ case Position.THREE: ++ this.silosSize[Position.THREE] = this.boundSiloSize(Position.THREE, groupSizeChange); ++ this.distributeRemainingSilosSize(Position.ONE, Position.TWO, availableSize - this.silosSize[Position.THREE]); ++ break; ++ default: ++ break; ++ } ++ default: ++ break; ++ } ++ this.layout(this.dimension); ++ ++ return true; ++ } ++ ++ protected boundSiloSize(siloPosition: Position, sizeChangePx: number): number {",`protected` => `private`?,2017-03-24 20:37:46 +863,"@@ -853,6 +857,83 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro + return ratio; + } + ++ // Request size change on the active editor/group - changes main axis ++ public requestActiveGroupSizeChange(groupSizeChange: number): boolean { ++ ++ enum VISIBLE_EDITORS { ++ ONE = 1, ++ TWO = 2, ++ THREE = 3 ++ } ++ ++ const visibleEditors = this.getVisibleEditorCount(); ++ ++ if (visibleEditors <= VISIBLE_EDITORS.ONE) { ++ return false; ++ } ++ ++ let availableSize = this.totalSize; ++ const activeGroupPosition = this.getActivePosition(); ++ ++ switch (visibleEditors) { ++ case VISIBLE_EDITORS.TWO: ++ switch (activeGroupPosition) { ++ case Position.ONE: ++ this.silosSize[Position.ONE] = this.boundSiloSize(Position.ONE, groupSizeChange); ++ this.silosSize[Position.TWO] = availableSize - this.silosSize[Position.ONE]; ++ break; ++ case Position.TWO: ++ this.silosSize[Position.TWO] = this.boundSiloSize(Position.TWO, groupSizeChange); ++ this.silosSize[Position.ONE] = availableSize - this.silosSize[Position.TWO]; ++ default: ++ break; ++ } ++ break; ++ case VISIBLE_EDITORS.THREE: ++ switch (activeGroupPosition) { ++ case Position.ONE: ++ this.silosSize[Position.ONE] = this.boundSiloSize(Position.ONE, groupSizeChange); ++ this.distributeRemainingSilosSize(Position.TWO, Position.THREE, availableSize - this.silosSize[Position.ONE]); ++ break; ++ case Position.TWO: ++ this.silosSize[Position.TWO] = this.boundSiloSize(Position.TWO, groupSizeChange); ++ this.distributeRemainingSilosSize(Position.ONE, Position.THREE, availableSize - this.silosSize[Position.TWO]); ++ break; ++ case Position.THREE: ++ this.silosSize[Position.THREE] = this.boundSiloSize(Position.THREE, groupSizeChange); ++ this.distributeRemainingSilosSize(Position.ONE, Position.TWO, availableSize - this.silosSize[Position.THREE]); ++ break; ++ default: ++ break; ++ } ++ default: ++ break; ++ } ++ this.layout(this.dimension); ++ ++ return true; ++ } ++ ++ protected boundSiloSize(siloPosition: Position, sizeChangePx: number): number { ++ const visibleEditors = this.getVisibleEditorCount(); ++ let newSiloSize: number = 0; ++ ++ newSiloSize = Math.max(this.minSize, this.silosSize[siloPosition] + sizeChangePx); ++ newSiloSize = Math.min(newSiloSize, (this.totalSize - this.minSize * (visibleEditors - 1))); ++ ++ return newSiloSize; ++ } ++ ++ protected distributeRemainingSilosSize(remPosition1: Position, remPosition2: Position, availableSize: number): void {",`protected` => `private`?,2017-03-24 20:37:51 +82,"@@ -86,7 +86,8 @@ class ExtHostApiCommands { + description: 'Execute signature help provider.', + args: [ + { name: 'uri', description: 'Uri of a text document', constraint: URI }, +- { name: 'position', description: 'Position in a text document', constraint: types.Position } ++ { name: 'position', description: 'Position in a text document', constraint: types.Position }, ++ { name: 'triggerCharacter', description: 'Trigger signature help when the user types the character, like `,` or `(`', constraint: String } + ],","this is an array and called triggerCharacters, also it's optional which I don't know if we express yet +",2016-03-22 10:58:51 +496,"@@ -87,8 +86,13 @@ export class UntitledEditorInput extends AbstractUntitledEditorInput { + return this.cachedModel.isDirty(); + } + +- // untitled files with an associated path or restore resource are always dirty +- return this.hasAssociatedFilePath || !!this.restoreResource; ++ // A disposed input is never dirty, even if it was restored from backup ++ if (this.isDisposed()) { ++ return false; ++ } ++ ++ // untitled files with an associated path or associated resource ++ return this.hasAssociatedFilePath || !!this.resource;","@Tyriar isn't that wrong? every untitled editor input will have a resource but will not be dirty when opened (e.g. open a new untitled file without content, it should not show dirty). +",2016-11-16 14:57:41 +723,"@@ -88,42 +88,82 @@ export function shorten(paths: string[]): string[] { + // for every path + let match = false; + for (let pathIndex = 0; pathIndex < paths.length; pathIndex++) { +- const path = paths[pathIndex]; ++ let path = paths[pathIndex]; ++ ++ if (path === '') { ++ shortenedPaths[pathIndex] = '.'; ++ continue; ++ } ++ ++ if (!path) { ++ shortenedPaths[pathIndex] = path; ++ continue; ++ } ++ + match = true; + ++ let prefix = ''; ++ // trim for now and concatenate network path (e.g. \\network) or root path (/etc) later ++ if (path.indexOf(`${nativeSep + nativeSep}`) === 0) {",I suggest to extract a new `const unc = ${nativeSep + nativeSep}`,2017-02-09 06:30:07 +724,"@@ -88,42 +88,82 @@ export function shorten(paths: string[]): string[] { + // for every path + let match = false; + for (let pathIndex = 0; pathIndex < paths.length; pathIndex++) { +- const path = paths[pathIndex]; ++ let path = paths[pathIndex]; ++ ++ if (path === '') { ++ shortenedPaths[pathIndex] = '.'; ++ continue; ++ } ++ ++ if (!path) { ++ shortenedPaths[pathIndex] = path; ++ continue; ++ } ++ + match = true; + ++ let prefix = ''; ++ // trim for now and concatenate network path (e.g. \\network) or root path (/etc) later ++ if (path.indexOf(`${nativeSep + nativeSep}`) === 0) { ++ prefix = path.substr(0, path.indexOf(`${nativeSep + nativeSep}`) + 2); ++ path = path.substr(path.indexOf(`${nativeSep + nativeSep}`) + 2); ++ } else if (path.indexOf(`${nativeSep}`) === 0) { ++ prefix = path.substr(0, path.indexOf(`${nativeSep}`) + 1);","Makes it unnecessarily hard to read to put a variable around ticks, just use `nativeSep` here?",2017-02-09 06:30:44 +820,"@@ -88,6 +88,30 @@ export function tildify(path: string, userHome: string): string { + * Shortens the paths but keeps them easy to distinguish. + * Replaces not important parts with ellipsis. + * Every shorten path matches only one original path and vice versa. ++ * ++ * Algorithm for shortening paths is as follows: ++ * 1. For every path in list, find unique substring of that path. ++ * 2. Unique substring along with ellipsis is shortened path of that path. ++ * 3. To find unique substring of path, consider every segment of length from 1 to path.length of path from end of string ++ * and if present segment is not substring to any other paths then present segment is unique path, ++ * else check if it is not present as suffix of any other path and present segment is suffix of path itself, ++ * if it is true take present segment as unique path. ++ * 4. Apply ellipsis to unique segment according to whether segment is present at start/in-between/end of path. ++ * ++ * Example 1 ++ * 1. consider 2 paths i.e. ['a\\b\\c\\d', 'a\\f\\b\\c\\d'] ++ * 2. find unique path of first path, ++ * a. 'd' is present in path2 and is suffix of path2, hence not unique of present path. ++ * b. 'c' is present in path2 and 'c' is not suffix of present path, similarly for 'b' and 'a' also. ++ * c. 'd\\c' is suffix of path2. ++ * d. 'b\\c' is not suffix of present path. ++ * e. 'a\\b' is not present in path2, hence unique path is 'a\\b...'. ++ * 3. for path2, 'f' is not present in path1 hence unique is '...\\f\\...'. ++ * ++ * Example 2 ++ * 1. consider 2 paths i.e. ['a\\b', 'a\\b\\c']. ++ * a. Even if 'b' is present in path2, as 'b' is suffix of path1 and is not suffix of path2, unique path will be '...\\b'. ++ * 2. for path2, 'c' is not present in path1 hence unique path is '..\\c'.","@bpasero @hun1ahpu @Tyriar Adding detailed algorithm. Please review. + +I think algorithm can be improved with the help of better data-structure, will create new PR with improved algorithm. + +Thanks :)",2017-03-13 12:12:36 +152,"@@ -889,7 +909,8 @@ export class Parser { + node.setExpression(this._parseStringLiteral()) || + node.setExpression(this._parseNumeric()) || + node.setExpression(this._parseHexColor()) || +- node.setExpression(this._parseOperation()) ++ node.setExpression(this._parseOperation()) || ++ node.setExpression(this._parseVariableExpression())","This needs to be before parseIndent (there could be an ident 'var'). Actually i'd rather do not have a _parseVariableExpression but let variable declarations be handled by _parseFunction. +",2016-05-20 09:59:25 +676,"@@ -898,6 +898,7 @@ export interface IWorkbenchEditorConfiguration { + editor: { + showTabs: boolean; + showTabCloseButton: boolean; ++ tabCloseButton: 'left' | 'right' | 'off';",remove `showTabCloseButton`,2017-01-16 07:59:57 +967,"@@ -899,6 +905,24 @@ export class CodeMenu { + } + } + ++ private setTaskMenu(taskMenu: Electron.Menu): void { ++ const runTask = this.createMenuItem(nls.localize({ key: 'miRunTask', comment: ['&& denotes a mnemonic'] }, ""&&Run Task...""), 'workbench.action.tasks.runTask'); ++ const restartTask = this.createMenuItem(nls.localize({ key: 'miRestartTask', comment: ['&& denotes a mnemonic'] }, ""&&Restart Task""), 'workbench.action.tasks.restartTask'); ++ const terminateTask = this.createMenuItem(nls.localize({ key: 'miTerminateTask', comment: ['&& denotes a mnemonic'] }, ""&&Terminate Task""), 'workbench.action.tasks.terminate'); ++ const buildTask = this.createMenuItem(nls.localize({ key: 'miBuildTask', comment: ['&& denotes a mnemonic'] }, ""&&Build Task""), 'workbench.action.tasks.build'); ++ const testTask = this.createMenuItem(nls.localize({ key: 'miTestTask', comment: ['&& denotes a mnemonic'] }, ""&&Test Task""), 'workbench.action.tasks.test'); ++ const showTaskLog = this.createMenuItem(nls.localize({ key: 'miShowTaskLog', comment: ['&& denotes a mnemonic'] }, ""&&Show Task Log""), 'workbench.action.tasks.showLog');","De-dupe the mnemonics here- R, T",2017-06-12 21:34:30 +55,"@@ -9,10 +9,28 @@ + + declare namespace vscode { + +- /** +- * The version of the editor. +- */ +- export var version: string;","that is API breakage which we cannot do +",2016-01-21 11:29:53 +56,"@@ -9,10 +9,28 @@ + + declare namespace vscode { + +- /** +- * The version of the editor. +- */ +- export var version: string; ++ export const env: { ++ /** ++ * The version of the editor. ++ */ ++ version: string; ++ ++ /** ++ * locale, like de-ch, en-us ++ */ ++ locale: string;","@dbaeumer We are looking into adding some vscode environment information. What do thing is needed for localisation support. Is a `locale` string enough? +",2016-01-21 11:30:53 +471,"@@ -9,11 +9,13 @@ import fs = require('fs'); + import path = require('path'); + import os = require('os'); + import assert = require('assert'); ++import crypto = require('crypto');","@Tyriar warnings in this file +",2016-11-09 07:39:16 +190,"@@ -9,21 +9,46 @@ import * as vscode from 'vscode'; + import * as path from 'path'; + import { ExtensionContext, TextDocumentContentProvider, EventEmitter, Event, Uri, ViewColumn } from ""vscode""; + +-const hljs = require('highlight.js'); +-const mdnh = require('markdown-it-named-headers'); +-const md = require('markdown-it')({ +- html: true, +- highlight: function (str, lang) { +- if (lang && hljs.getLanguage(lang)) { +- try { +- return `
${hljs.highlight(lang, str, true).value}
`; +- } catch (error) { } ++let md; ++let userStyles = []; ++ ++export function activate(context: ExtensionContext) { ++ // Upon activation, load markdown module with default ++ // plugins, and then load any user-defined plugins. ++ // Note: user-defined plugins may override default plugins. ++ const hljs = require('highlight.js');","Would suggest a better naming for the hljs. const HIGHLIGHT? Same for the const below MARKDOWN_HEADERS? And out of curiosity why are the const namings not ALL_CAPS? I cannot find this back in the https://github.com/Microsoft/vscode/wiki/Coding-Guidelines +",2016-06-21 11:29:28 +188,"@@ -9,21 +9,46 @@ import * as vscode from 'vscode'; + import * as path from 'path'; + import { ExtensionContext, TextDocumentContentProvider, EventEmitter, Event, Uri, ViewColumn } from ""vscode""; + +-const hljs = require('highlight.js'); +-const mdnh = require('markdown-it-named-headers'); +-const md = require('markdown-it')({ +- html: true, +- highlight: function (str, lang) { +- if (lang && hljs.getLanguage(lang)) { +- try { +- return `
${hljs.highlight(lang, str, true).value}
`; +- } catch (error) { } ++let md; ++let userStyles = []; ++ ++export function activate(context: ExtensionContext) { ++ // Upon activation, load markdown module with default ++ // plugins, and then load any user-defined plugins. ++ // Note: user-defined plugins may override default plugins. ++ const hljs = require('highlight.js'); ++ const mdnh = require('markdown-it-named-headers');","Put it into a special list, maybe called `builtInPlugins` and merge it with `userPlugins` at runtime? +",2016-06-20 10:02:31 +189,"@@ -9,21 +9,46 @@ import * as vscode from 'vscode'; + import * as path from 'path'; + import { ExtensionContext, TextDocumentContentProvider, EventEmitter, Event, Uri, ViewColumn } from ""vscode""; + +-const hljs = require('highlight.js'); +-const mdnh = require('markdown-it-named-headers'); +-const md = require('markdown-it')({ +- html: true, +- highlight: function (str, lang) { +- if (lang && hljs.getLanguage(lang)) { +- try { +- return `
${hljs.highlight(lang, str, true).value}
`; +- } catch (error) { } ++let md; ++let userStyles = []; ++ ++export function activate(context: ExtensionContext) { ++ // Upon activation, load markdown module with default ++ // plugins, and then load any user-defined plugins. ++ // Note: user-defined plugins may override default plugins. ++ const hljs = require('highlight.js'); ++ const mdnh = require('markdown-it-named-headers'); ++ md = require('markdown-it')({ ++ html: true, ++ highlight: function (str, lang) { ++ if (lang && hljs.getLanguage(lang)) { ++ try { ++ return `
${hljs.highlight(lang, str, true).value}
`; ++ } catch (error) { } ++ } ++ return `
${md.utils.escapeHtml(str)}
`; + } +- return `
${md.utils.escapeHtml(str)}
`; ++ }).use(mdnh, {}); ++ ++ // Load user-defined packages ++ const userPlugins = >vscode.workspace.getConfiguration('markdown')['plugins']; ++ if (userPlugins && Array.isArray(userPlugins)) {","This can be a single `instanceof Array` +",2016-06-20 10:04:30 +183,"@@ -9,26 +9,41 @@ + + ","I didn't realize we were hardcoding this, thanks for moving it to an env value." +3,"@@ -99,7 +99,7 @@ module.exports = function fileItem (props) { + } + +
+- ${file.data.size && html`
${prettyBytes(file.data.size)}
`} ++ ${isNaN(file.data.size) ? '' : html`
${prettyBytes(file.data.size)}
`} + ${file.source && html`
+ ${acquirers.map(acquirer => { + if (acquirer.id === file.source) return html`${acquirer.icon()}`","We are trying to support IE 10-11, so we'll need a polyfill for this one, I think." +4,"@@ -38,6 +38,9 @@ const { useSelect, useDispatch } = Data; + function ResetButton( { children } ) { + const postResetURL = useSelect( ( select ) => select( CORE_SITE ).getAdminURL( 'googlesitekit-splash', { notification: 'reset_success' } ) ); + ++ const isNavigating = useSelect( ( select ) => select( CORE_LOCATION ).isNavigating() ); ++ const navigatingURL = useSelect( ( select ) => select( CORE_LOCATION ).getNavigateURL() ); ++ + const [ dialogActive, setDialogActive ] = useState( false ); + + useEffect( () => {",It looks like there's a new `isNavigatingTo( url )` selector for this very purpose so let's use this here instead. This way we just need to use the one selector rather than two. Let's assign that to a similar-named variable here (e.g. `isNavigatingToPostResetURL`) rather than the prop it's used with. +5,"@@ -29,8 +29,8 @@ + + namespace lbann { + +-void im2col(const Mat& im, +- Mat& col, ++void im2col(const AbsMat& im, ++ AbsMat& col, + const int num_channels, + const int im_num_dims, + const int * im_dims,",I think im2col should only accommodate CPUMat. +6,"@@ -24,6 +24,8 @@ from google.cloud.forseti.notifier.notifiers import cscc_notifier + from google.cloud.forseti.notifier.notifiers.inventory_summary import InventorySummary + from google.cloud.forseti.services.inventory.storage import DataAccess + from google.cloud.forseti.services.scanner import dao as scanner_dao ++from google.cloud.forseti.common.util.email.email_factory import EmailFactory ++from google.cloud.forseti.notifier.notifiers import email_violations + # pylint: enable=line-too-long + + ",alpha sort the imports +7,"@@ -1067,7 +1067,7 @@ fpga_result mmio_error(struct RASCommandLine *rasCmdLine) + if ( rasCmdLine->function >0 ) + function = rasCmdLine->bus; + +- snprintf(sysfs_path, sizeof(sysfs_path), ++ snprintf_s_iiii(sysfs_path, sizeof(sysfs_path), + DEVICEID_PATH,0,bus,device,function); + + result = sysfs_read_u64(sysfs_path, &value);",Can you explain why is this necessary? Is `snprintf()` with four integer arguments unsafe? +8,"@@ -219,7 +219,19 @@ def internal_keyDownEvent(vkCode,scanCode,extended,injected): + for k in range(256): + keyStates[k]=ctypes.windll.user32.GetKeyState(k) + charBuf=ctypes.create_unicode_buffer(5) ++ # First try getting the keyboard layout from the thread with the focus (input thread) + hkl=ctypes.windll.user32.GetKeyboardLayout(focus.windowThreadID) ++ if not hkl: ++ log.debug(""Failed to fetch keyboard layout from focus, trying layout from last detected change"") ++ # Some threads, such as for Windows consoles ++ # Do not allow getKeyboardLayout to work. ++ # Therefore, use the cached keyboard layout from the last inputLangChange detected by NVDA ++ # on the foreground object. ++ hkl = getattr(api.getForegroundObject(), '_lastDetectedKeyboardLayoutChange', 0) ++ if not hkl: ++ log.debug(""No layout cached, falling back to layout of NVDA main thread"") ++ # As a last resort, use the keyboard layout of NVDA's main thread. ++ hkl = ctypes.windll.user32.GetKeyboardLayout(core.mainThreadId) + # In previous Windows builds, calling ToUnicodeEx would destroy keyboard buffer state and therefore cause the app to not produce the right WM_CHAR message. + # However, ToUnicodeEx now can take a new flag of 0x4, which stops it from destroying keyboard state, thus allowing us to safely call it here. + res=ctypes.windll.user32.ToUnicodeEx(vkCode,scanCode,keyStates,charBuf,len(charBuf),0x4,hkl)",How likely would it be that the keyboard layout for the NVDA main thread differs from the keyboard layout of the currently focused app? +9,"@@ -198,6 +198,10 @@ class Driver extends webdriver.WebDriver { + * @return {!Driver} A new driver instance. + */ + static createSession(options, service = getDefaultService()) { ++ if (!service) { ++ service = getDefaultService(); ++ } ++ + let client = service.start().then(url => new http.HttpClient(url)); + let executor = new http.Executor(client); + ",Would you mind removing the default parameter above? (I doubt I'll ever use defaults again since you still have to protect against callers explicitly passing `null` or `undefined`) +10,"@@ -2186,7 +2186,7 @@ class WebElement { + if (!this.driver_.fileDetector_) { + return this.schedule_( + new command.Command(command.Name.SEND_KEYS_TO_ELEMENT). +- setParameter('text', keys). ++ setParameter('text', keys.then(keys => keys.join(''))). + setParameter('value', keys), + 'WebElement.sendKeys()'); + }",Also update line 2205 below +11,"@@ -39,6 +39,7 @@ func (p *Provisioner) ProvisionHostPath(opts pvController.VolumeOptions, volumeC + name := opts.PVName + stgType := volumeConfig.GetStorageType() + saName := getOpenEBSServiceAccountName() ++ shared := volumeConfig.GetSharedMountValue() + + path, err := volumeConfig.GetPath() + if err != nil {","n_: It is a good practice to name the variable to indicate what they contain. In this case since `shared` is supposed to have boolean, calling it: `isShared` can help in the readability of the code." +12,"@@ -85,7 +85,10 @@ export class ManualColumnFreeze extends BasePlugin { + } + + /** +- * Freezes the given column (add it to fixed columns). ++ * Freezes the specified column (i.e. adds it to fixed columns). ++ * ++ * `freezeColumn()` doesn't re-render the table, ++ * so you need to call the `render()` method afterward. + * + * @param {number} column Visual column index. + */",I suppose it's a false-positive error. Maybe there is a way to configure the `eslint-*` package to accept `i.e. .... lower case` syntax +13,"@@ -133,7 +133,7 @@ namespace OpenTelemetry.Trace + private void RunGetRequestedDataOtherSampler(Activity activity) + { + ActivityContext parentContext; +- if (string.IsNullOrEmpty(activity.ParentId)) ++ if (string.IsNullOrEmpty(activity.ParentId) || activity.ParentSpanId.ToHexString().Equals(""0000000000000000"")) + { + parentContext = default; + }","this maynot be a perf issue, if ToHexString() is not actually allocating a string, but returns the caches string value. to be confirmed." +14,"@@ -114,11 +114,16 @@ func (w *watcher) run(ctx context.Context, provider imageprovider.Provider, inte + updates = append(updates, u...) + } + if len(updates) == 0 { +- w.logger.Info(""no image to be updated"") ++ w.logger.Info(""no image to be updated"", ++ zap.String(""image-provider"", provider.Name()), ++ ) + continue + } + if err := update(updates); err != nil { +- w.logger.Error(""failed to update image"", zap.Error(err)) ++ w.logger.Error(""failed to update image"", zap.String(""image-provider"", ++ provider.Name()), ++ zap.Error(err), ++ ) + continue + } + }","`zap.String(""image-provider"", provider.Name())` should be in a same line." +15,"@@ -1,8 +1,6 @@ + /*exported DqElement */ + + function truncate(str, maxLength) { +- 'use strict'; +- + maxLength = maxLength || 300; + + if (str.length > maxLength) {",Why this deletion? +16,"@@ -419,7 +419,10 @@ class S3KeyTest(unittest.TestCase): + remote_metadata = check._get_remote_metadata() + + # TODO: investigate whether encoding ' ' as '%20' makes sense +- self.assertEqual(check.cache_control, 'public,%20max-age=500') ++ self.assertIn( ++ check.cache_control, ++ ('public,%20max-age=500', 'public, max-age=500') ++ ) + self.assertEqual(remote_metadata['cache-control'], 'public,%20max-age=500') + self.assertEqual(check.get_metadata('test-plus'), 'A plus (+)') + self.assertEqual(check.content_disposition, 'filename=Sch%C3%B6ne%20Zeit.txt')",This change looks unrelated to the CL description? +17,"@@ -18,7 +18,7 @@ class DedupTest : public QueryTestBase { + void SetUp() override { QueryTestBase::SetUp(); } + }; + +-#define DEDUP_RESUTL_CHECK(inputName, outputName, sentence, expected) \ ++#define DEDUP_RESULT_CHECK(inputName, outputName, sentence, expected) \ + do { \ + qctx_->symTable()->newVariable(outputName); \ + auto yieldSentence = getYieldSentence(sentence, qctx_.get()); \",I'm not certain that `res`+`utl` isn't a thing. +18,"@@ -182,6 +182,7 @@ public class FetchActiveFlowDao { + + "" LEFT JOIN "" + + "" executors et ON ex.executor_id = et.id"" + + "" WHERE ex.status NOT IN ("" ++ + Status.EXECUTION_STOPPED.getNumVal() + "", "" + + Status.SUCCEEDED.getNumVal() + "", "" + + Status.KILLED.getNumVal() + "", "" + + Status.FAILED.getNumVal() + "")"";","This method can cause bugs. Why don't you use list of finalize statuses and then use join by comma and that will give you correct value. Use Apache Commons Lang library List list = Arrays.asList(1,2,3,4,5,6,7); String str = org.apache.commons.lang.StringUtils.join(list, "",""); You can use it at multiple places shown in this diff." +19,"@@ -23,7 +23,10 @@ void wlr_input_device_init(struct wlr_input_device *dev, + } + + void wlr_input_device_destroy(struct wlr_input_device *dev) { +- if (!dev) return; ++ if (!dev) { ++ return; ++ } ++ + if (dev->_device) { + switch (dev->type) { + case WLR_INPUT_DEVICE_KEYBOARD:",Merge with next condition +20,"@@ -348,6 +348,7 @@ type appResourcesGetter interface { + + type taskDeployer interface { + DeployTask(input *deploy.CreateTaskResourcesInput, opts ...cloudformation.StackOption) error ++ DeleteTask(task deploy.TaskStackInfo) error + } + + type taskRunner interface {",Maybe add it when it is used. +21,"@@ -36,3 +36,17 @@ TWO_ENABLED = {'scanners': [ + {'name': 'cloudsql_acl', 'enabled': False}, + {'name': 'iam_policy', 'enabled': True} + ]} ++ ++NONEXIST_ENABLED = {'scanners': [ ++ {'name': 'bigquery', 'enabled': False}, ++ {'name': 'bucket_acl', 'enabled': True}, ++ {'name': 'cloudsql_acl', 'enabled': False}, ++ {'name': 'non_exist_scanner', 'enabled': True} ++]} ++ ++ALL_EXIST = {'scanners': [ ++ {'name': 'bigquery', 'enabled': True}, ++ {'name': 'bucket_acl', 'enabled': True}, ++ {'name': 'cloudsql_acl', 'enabled': True}, ++ {'name': 'iam_policy', 'enabled': True} ++]}",More clear naming: NONEXISTENT_ENABLED +22,"@@ -282,10 +282,10 @@ public class TypeUtil { + + switch (from.typeId()) { + case INTEGER: +- return to == Types.LongType.get(); ++ return to.equals(Types.LongType.get()); + + case FLOAT: +- return to == Types.DoubleType.get(); ++ return to.equals(Types.DoubleType.get()); + + case DECIMAL: + Types.DecimalType fromDecimal = (Types.DecimalType) from;",why is this change necessary? +23,"@@ -178,9 +178,8 @@ public class SchemaTypeTable implements ImportTypeTable, SchemaTypeFormatter { + + @Override + public String getFullNameFor(TypeModel type) { +- // TODO(andrealin): Remove this hack when null response types are implemented. +- if (type == null) { +- return ""nullFullName""; ++ if (type.isEmptyType()) { ++ return ""java.lang.Void""; + } + if (type instanceof DiscoveryRequestType) { + Method method = ((DiscoveryRequestType) type).parentMethod().getDiscoMethod();",make a SchemaTypeNameConverter.getTypeNameForEmptyType() and call that here. +24,"@@ -26,7 +26,10 @@ class TinyMCELanguage extends AbstractSmartyPlugin + + public function __construct(Request $request) + { +- $this->locale = $request->getSession()->getLang()->getLocale(); ++ if($request->getSession() != null) ++ $this->locale = $request->getSession()->getLang()->getLocale(); ++ else ++ $this->locale = Lang::getDefaultLanguage()->getLocale(); + } + + public function guessTinyMCELanguage($params, \Smarty_Internal_Template $template)",Use braces on your conditional structures please +25,"@@ -16,6 +16,7 @@ + + DECLARE_string(u); + DECLARE_string(p); ++DEFINE_bool(enable_history, false, ""Whether to force saving the command history""); + + namespace nebula { + namespace graph {","Great God, I have a question. This "".nebula_history"" file is used to save history commands. Is there a file size limit? When the file is large, does it take a long time to start initialization (loadHistory)? How did you think about this? Thx." +26,"@@ -1004,8 +1004,9 @@ static void parseRecord (tokenInfo *const token) + */ + if (!isType (token, TOKEN_OPEN_PAREN)) + readToken (token); ++ if (!isType (token, TOKEN_OPEN_PAREN)) ++ return; + +- Assert (isType (token, TOKEN_OPEN_PAREN)); + do + { + if (isType (token, TOKEN_COMMA) ||",Isn't this the same check as two lines above? +27,"@@ -18,8 +18,11 @@ from mitmproxy import io + from mitmproxy import log + from mitmproxy import version + from mitmproxy import optmanager ++from mitmproxy import options + import mitmproxy.tools.web.master # noqa + ++CONFIG_PATH = os.path.join(options.CA_DIR, 'config.yaml') ++ + + def flow_to_json(flow: mitmproxy.flow.Flow) -> dict: + """"""","Don't redefine, just import the existing one in `cmdline.py`. :)" +28,"@@ -92,7 +92,8 @@ module Mongoid + # + # @since 2.0.0.rc.7 + def process_attribute(name, value) +- if store_as = aliased_fields.invert[name.to_s] ++ responds = respond_to?(""#{name}="") ++ if !responds && store_as = aliased_fields.invert[name.to_s] + name = store_as + end + responds = respond_to?(""#{name}="")","why not call `respond_to?(""#{name}="")` from the `if` line?" +29,"@@ -215,7 +215,8 @@ public final class BlazeCidrLauncher extends CidrLauncher { + workingDir = workspaceRootDirectory; + } + +- GeneralCommandLine commandLine = new GeneralCommandLine(runner.executableToDebug.getPath()); ++ GeneralCommandLine commandLine = new GeneralCommandLine(runner.executableToDebug.getPath()) ++ .withWorkDirectory(workingDir); + + commandLine.addParameters(handlerState.getExeFlagsState().getFlagsForExternalProcesses()); + commandLine.addParameters(handlerState.getTestArgs());",This was properly set above as `.runfiles/` (with a fallback to workspace root dir) but never used past this line. +30,"@@ -0,0 +1,13 @@ ++using System; ++using System.Collections.Generic; ++using System.Linq; ++using System.Text; ++using System.Threading.Tasks; ++using MvvmCross.Core.Views; ++ ++namespace MvvmCross.Uwp.Attributes ++{ ++ public class MvxPagePresentationAttribute : MvxBasePresentationAttribute ++ { ++ } ++}",Are all these namespaces required for this attribute? +31,"@@ -53,9 +53,12 @@ module Beaker + result.stdout << std_out + result.stderr << std_err + result.exit_code = status.exitstatus ++ @logger.info(result.stdout) ++ @logger.info(result.stderr) + end + rescue => e + result.stderr << e.inspect ++ @logger.info(result.stderr) + result.exit_code = 1 + end + ","Given this may be used and printed in other ways, isn't `debug` more appropriate?" +32,"@@ -540,3 +540,7 @@ func (s *blockDiskStore) remove(id kbfsblock.ID) error { + } + return err + } ++ ++func (s blockDiskStore) clear() error { ++ return ioutil.RemoveAll(s.dir) ++}",Looks like this is unused? Did you mean to call it when clearing the block journal? +33,"@@ -117,8 +117,10 @@ public class ExecutorManager extends EventHandler implements + + public ExecutorManager(Props props, ExecutorLoader loader, + Map alters) throws ExecutorManagerException { ++ alerters = alters; + azkProps = props; + this.executorLoader = loader; ++ + this.setupExecutors(); + this.loadRunningFlows(); + ",why named alters? how about this.alerts = alerts? +34,"@@ -1549,7 +1549,7 @@ func (js *jetStream) processStreamLeaderChange(mset *stream, isLeader bool) { + resp.Error = jsError(err) + s.sendAPIErrResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + } else { +- resp.StreamInfo = &StreamInfo{Created: mset.createdTime(), State: mset.state(), Config: mset.config(), Cluster: js.clusterInfo(mset.raftGroup())} ++ resp.StreamInfo = &StreamInfo{Created: mset.createdTime(), State: mset.state(), Config: mset.config(), Cluster: js.clusterInfo(mset.raftGroup()), Sources: mset.sourcesInfo(), Mirror: mset.mirrorInfo()} + s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + if node := mset.raftNode(); node != nil { + mset.sendCreateAdvisory()",not sure if this has to be here or not tbh +35,"@@ -72,7 +72,12 @@ func newHarnessUsingAutodelete(ctx context.Context, t *testing.T) (drivertest.Ha + } + + func (h *harness) CreateTopic(ctx context.Context, testName string) (dt driver.Topic, cleanup func(), err error) { ++ // Keep the topic entity name under 50 characters as per Azure limits. ++ // See https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-quotas + topicName := fmt.Sprintf(""%s-topic-%d"", sanitize(testName), atomic.AddUint32(&h.numTopics, 1)) ++ if len(topicName) > 50 { ++ topicName = topicName[:50] ++ } + + createTopic(ctx, topicName, h.ns, nil) + ","There's a better fix for this in #1741, which should replace this." +36,"@@ -63,7 +63,7 @@ func (s *StreamMock) Close() error { + func TestHandshake(t *testing.T) { + logger := logging.New(ioutil.Discard, 0) + info := Info{ +- Address: ""node1"", ++ Address: []byte(""node1""), + NetworkID: 0, + Light: false, + }","Use swarm.Address not []byte as type, and construct it from actual byteslice or use swarm.NewAddress if it is constructed from hex-encoded string." +37,"@@ -80,8 +80,9 @@ func TestFSRepoInit(t *testing.T) { + + dir, err := ioutil.TempDir("""", """") + assert.NoError(t, err) +- +- defer os.RemoveAll(dir) ++ defer func() { ++ require.NoError(t, os.RemoveAll(dir)) ++ }() + + t.Log(""init FSRepo"") + assert.NoError(t, InitFSRepo(dir, config.NewDefaultConfig()))","It would be worth factoring this out to a function, but you don't have to do that here." +38,"@@ -0,0 +1,15 @@ ++package com.fsck.k9.message.html; ++ ++/** ++ * General framework to handle uris when parsing. Allows different handling depending on the scheme identifier. ++ */ ++public interface UriParser { ++ /** ++ * Parse and linkify scheme specific uri beginning from given position. The result will be written to given buffer. ++ * @param text String to parse uri from. ++ * @param startPos Position where uri starts (first letter of scheme). ++ * @param outputBuffer Buffer where linkified variant of uri is written to. ++ * @return Index where parsed uri ends (first non-uri letter). Should be startPos or smaller if no valid uri was found. ++ */ ++ int linkifyUri(String text, int startPos, StringBuffer outputBuffer); ++}",There's no need for `final` in interfaces. +39,"@@ -101,6 +101,9 @@ namespace Datadog.Trace.OpenTracing + case DatadogTags.ServiceName: + Span.ServiceName = value; + return this; ++ case DatadogTags.ServiceVersion: ++ Span.SetTag(Tags.Version, value); ++ return this; + } + + if (key == global::OpenTracing.Tag.Tags.Error.Key)",Isn't this case handled as a custom tag in `Span.SetTag()` below? This switch is only for special tags that actually set `Span` properties. +40,"@@ -681,7 +681,6 @@ class Quitter: + @cmdutils.argument('session', completion=miscmodels.session) + def quit(self, save=False, session=None): + """"""Quit qutebrowser. +- + Args: + save: When given, save the open windows even if auto_save.session + is turned off.",This shouldn't be changed. +41,"@@ -1,5 +1,5 @@ + ## This file is part of Invenio. +-## Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 CERN. ++## Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014 CERN. + ## + ## Invenio is free software; you can redistribute it and/or + ## modify it under the terms of the GNU General Public License as","This one is important `2: I102 copyright year is outdated, expected 2014 but got 2012`" +42,"@@ -32,6 +32,8 @@ import java.util.Map; + import java.util.Optional; + import java.util.Set; + import java.util.concurrent.TimeoutException; ++import java.util.function.BiConsumer; ++import java.util.function.Consumer; + + import com.google.common.collect.Lists; + import com.google.common.collect.Maps;","Are these imports needed (BiConsumer and Consumer)? If they are unused imports, then precommit will fail." +43,"@@ -0,0 +1,10 @@ ++class TraceDestroyerJob < ApplicationJob ++ queue_as :default ++ ++ def perform(trace) ++ trace.destroy ++ rescue StandardError => ex ++ logger.info ex.to_s ++ ex.backtrace.each { |l| logger.info l } ++ end ++end",Why are we catching and logging exceptions? By doing that we make it look like the job has succeeded and it will be removed from the queue - if we didn't do that then it would stay queued... +44,"@@ -90,14 +90,11 @@ class CartController extends FrontBaseController + */ + public function indexAction(Request $request) + { +- $cart = $this->cartFacade->getCartOfCurrentCustomer(); +- +- if ($cart->isEmpty()) { +- $this->cartFacade->cleanAdditionalData(); +- } ++ $cart = $this->cartFacade->findCartOfCurrentCustomer(); ++ $cartItems = $cart === null ? [] : $cart->getItems(); + + $cartFormData = ['quantities' => []]; +- foreach ($cart->getItems() as $cartItem) { ++ foreach ($cartItems as $cartItem) { + $cartFormData['quantities'][$cartItem->getId()] = $cartItem->getQuantity(); + } + ","If there are `@param` tags in docblock, there should be `@return` tag also. (applies for a whole file)" +45,"@@ -34,7 +34,8 @@ public enum BesuMetricCategory implements MetricCategory { + PRUNER(""pruner""), + RPC(""rpc""), + SYNCHRONIZER(""synchronizer""), +- TRANSACTION_POOL(""transaction_pool""); ++ TRANSACTION_POOL(""transaction_pool""), ++ VALIDATORS(""validators""); + + private static final Optional BESU_PREFIX = Optional.of(""besu_""); + public static final Set DEFAULT_METRIC_CATEGORIES;",Is the concept of validators exclusive to IBFT2? I wonder if this category should be more explicitly linked to IBFT2. +46,"@@ -14,9 +14,7 @@ + */ + package org.hyperledger.besu.tests.acceptance.dsl.account; + +-import org.hyperledger.besu.crypto.SECP256K1.KeyPair; +-import org.hyperledger.besu.crypto.SECP256K1.PrivateKey; +-import org.hyperledger.besu.crypto.SECP256K1.PublicKey; ++import org.hyperledger.besu.crypto.*; + import org.hyperledger.besu.ethereum.core.Address; + import org.hyperledger.besu.ethereum.core.Hash; + import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount;",Spotless is configured to reject star imports. Please replace with explicit imports. +47,"@@ -115,6 +115,8 @@ void SYCLInternal::initialize(const sycl::device& d) { + + m_maxThreadsPerSM = + d.template get_info(); ++ m_maxShmemPerBlock = ++ d.template get_info(); + m_indirectKernelMem.reset(*m_queue); + m_indirectReducerMem.reset(*m_queue); + } else {",Remind me why you are using CUDA vocabulary when naming these variables. +48,"@@ -898,6 +898,16 @@ public final class DBReader { + } + final LongIntMap feedCounters = adapter.getFeedCounters(feedIds); + ++ int feedFilter = UserPreferences.getFeedFilter(); ++ if (feedFilter == UserPreferences.FEED_FILTER_COUNTER_ZERO) { ++ for (int i = 0; i < feeds.size(); i++) { ++ if (feedCounters.get(feeds.get(i).getId()) <= 0) { ++ feedCounters.delete(feeds.get(i).getId()); ++ feeds.remove(i); ++ } ++ } ++ } ++ + Comparator comparator; + int feedOrder = UserPreferences.getFeedOrder(); + if (feedOrder == UserPreferences.FEED_ORDER_COUNTER) {",Please turn the iteration order around (instead of `0...size` to `size...0`). The reason is that this sometimes skips indices when removing an item. You can therefore end up with feeds that have counter 0 and are still displayed. +49,"@@ -620,7 +620,7 @@ def execute_reentrant_pipeline(pipeline, typed_environment, throw_on_error, reen + def get_subset_pipeline(pipeline, solid_subset): + check.inst_param(pipeline, 'pipeline', PipelineDefinition) + check.opt_list_param(solid_subset, 'solid_subset', of_type=str) +- return pipeline if solid_subset is None else build_sub_pipeline(pipeline, solid_subset) ++ return pipeline if not solid_subset else build_sub_pipeline(pipeline, solid_subset) + + + def create_typed_environment(pipeline, environment=None):",this is a behavior change. solid_subset=[] represents an empty pipeline where as solid_subset=None is the full pipeline +50,"@@ -318,8 +318,7 @@ Licensed under the MIT License. See License.txt in the project root for license + { + foreach (var unmatchedSetting in CustomSettings.Keys) + { +- Logger.LogError(new ArgumentException(unmatchedSetting), +- Resources.ParameterIsNotValid, unmatchedSetting); ++ Logger.LogWarning(Resources.ParameterIsNotValid, unmatchedSetting); + } + } + ErrorManager.ThrowErrors();","this is a breaking change, any specific reason you want to do this?" +51,"@@ -91,6 +91,8 @@ type nodeChainReader interface { + GetTipSetStateRoot(tsKey types.SortedCidSet) (cid.Cid, error) + HeadEvents() *ps.PubSub + Load(context.Context) error ++ PutTipSetAndState(context.Context, *chain.TipSetAndState) error ++ SetHead(context.Context, types.TipSet) error + Stop() + } + ","Blocking: we still want read write separation. Node functions should absolutely not write to the chain store and the interface should reflect that. Only the syncer should have this capability in production code. It should be no problem to keep casting chainForTest to a read-write interface, or doing other function decomposition and automatic casting tricks." +52,"@@ -22,7 +22,8 @@ const ( + minimalPrefetchWorkerQueueSize int = 1 + testBlockRetrievalWorkerQueueSize int = 5 + testPrefetchWorkerQueueSize int = 1 +- defaultOnDemandRequestPriority int = 100 ++ defaultOnDemandRequestPriority int = 1<<30 - 1 ++ lowestTriggerPrefetchPriority int = 1 + // Channel buffer size can be big because we use the empty struct. + workerQueueSize int = 1<<31 - 1 + )",The PR description says the lowest on-demand request priority is `2^30`. Why the `-1` here? +53,"@@ -609,6 +609,14 @@ bool Game::removeCreature(Creature* creature, bool isLogout/* = true*/) + return true; + } + ++void Game::executeDeath(uint32_t creatureId) ++{ ++ Creature* creature = getCreatureByID(creatureId); ++ if (creature && !creature->isRemoved() && creature->getHealth() < 1) { ++ creature->onDeath(); ++ } ++} ++ + void Game::playerMoveThing(uint32_t playerId, const Position& fromPos, + uint16_t spriteId, uint8_t fromStackPos, const Position& toPos, uint8_t count) + {",checking health again? I think it is not necessary. +54,"@@ -442,7 +442,18 @@ configRetry: + log.Infof(""Starting the Typha connection"") + err := typhaConnection.Start(context.Background()) + if err != nil { +- log.WithError(err).Fatal(""Failed to connect to Typha"") ++ log.WithError(err).Error(""Failed to connect to Typha. Retrying..."") ++ startTime := time.Now() ++ for err != nil && time.Since(startTime) < 30*time.Second { ++ // Set Ready to false and Live to true when unable to connect to typha ++ healthAggregator.Report(healthName, &health.HealthReport{Live: true, Ready: false}) ++ err = typhaConnection.Start(context.Background()) ++ log.WithError(err).Debug(""Retrying to start Typha"") ++ time.Sleep(1 * time.Second) ++ } ++ if err != nil { ++ log.WithError(err).Fatal(""Failed to connect to Typha"") ++ } + } + go func() { + typhaConnection.Finished.Wait()",Need an `if err == nil {break}` above this line so that we don't log/sleep if the retry succeeds. +55,"@@ -0,0 +1,18 @@ ++'use strict'; ++ ++const assert = require('assert'); ++ ++class ProvidedPromise { ++ set Promise(lib) { ++ assert.ok(typeof lib === 'function', `mongodb.Promise must be a function, got ${lib}`); ++ this._promise = lib; ++ } ++ get Promise() { ++ return this._promise; ++ } ++} ++ ++const provided = new ProvidedPromise(); ++provided.Promise = global.Promise; ++ ++module.exports = provided;","to reiterate my point above, this class is not the actual provided Promise, but rather something a user can provide a Promise to/with. I think a name like `PromiseProvider` is more appropriate." +56,"@@ -738,6 +738,12 @@ func addDep(s *scope, args []pyObject) pyObject { + dep := core.ParseBuildLabelContext(string(args[1].(pyString)), s.pkg) + exported := args[2].IsTruthy() + target.AddMaybeExportedDependency(dep, exported, false, false) ++ // Queue this dependency if it'll be needed. ++ if target.State() > core.Inactive { ++ err := s.state.QueueTarget(dep, target.Label, true, false) ++ s.Assert(err == nil, ""%s"", err) ++ } ++ // TODO(peterebden): Do we even need the following any more? + s.pkg.MarkTargetModified(target) + return None + }","I guess we can only call this from a post-build function, but we might need to check that this target is to be built? I guess target A depends on B which has a post build. We `plz build :B` which adds C as a dep of A. Won't we queue C to be built even though it only needs to build if A needs to be built? That's kinda why I approached this the way I did. I trust you've thought about this but would be good to understand this a bit better." +57,"@@ -123,7 +123,7 @@ def sndrcv(pks, pkt, timeout = None, inter = 0, verbose=None, chainCC=0, retry=0 + if remaintime <= 0: + break + r = None +- if arch.FREEBSD or arch.DARWIN: ++ if not (pks.__class__.__name__ == 'StreamSocket') and (arch.FREEBSD or arch.DARWIN): + inp, out, err = select(inmask,[],[], 0.05) + if len(inp) == 0 or pks in inp: + r = pks.nonblock_recv()",You should use `isinstance()` instead of comparing the class name to a string. +58,"@@ -15,6 +15,11 @@ axe.utils.isHidden = function isHidden(el, recursed) { + return false; + } + ++ // do not exclude `video` or `audio` el's ++ if ([`VIDEO`, `AUDIO`].includes(el.nodeName.toUpperCase())) { ++ return false; ++ } ++ + // 11 === Node.DOCUMENT_FRAGMENT_NODE + if (el.nodeType === 11) { + el = el.host; // grab the host Node",Why should audio and video elements always return `false` for `isHidden`? +59,"@@ -27,7 +27,7 @@ namespace Playground.Core + + Mvx.IoCProvider.RegisterSingleton(new TextProviderBuilder().TextProvider); + +- RegisterAppStart(); ++ // RegisterAppStart(); + } + + /// ",This obviously won't work for all the other platforms. +60,"@@ -15,7 +15,7 @@ public class ManipulationTest extends BasicJBehaveTest { + + @Override + public InjectableStepsFactory stepsFactory() { +- Map state = new HashMap(); ++ Map state = new HashMap<>(); + + return new InstanceStepsFactory(configuration(), + new SharedSteps(state),",Isn't he diamond operator Java7+? +61,"@@ -159,6 +159,17 @@ public final class Require { + return number; + } + ++ public static double positive(String argName, double number, String message) { ++ if (number <= 0) { ++ if (message == null) { ++ throw new IllegalArgumentException(argName + "" must be greater than 0""); ++ } else { ++ throw new IllegalArgumentException(message); ++ } ++ } ++ return number; ++ } ++ + public static int positive(String argName, Integer number) { + return positive(argName, number, null); + }","Prefer adding a second `positive(String, double)` that delegates down to this three-param version. Using `null` in code is generally Not A Great Idea, and it looks ugly." +62,"@@ -474,7 +474,7 @@ func (rule removeCount) Name() string { + func (rule removeCount) Pattern() plan.Pattern { + return plan.Pat(universe.CountKind, plan.Any()) + } +-func (rule removeCount) Rewrite(ctx context.Context, node plan.Node) (plan.Node, bool, error) { ++func (rule removeCount) Rewrite(ctx context.Context, node plan.Node, nextNodeId *int) (plan.Node, bool, error) { + return node.Predecessors()[0], true, nil + } + ","This pattern, where we add a new parameter without using it, often indicates to me that we've got a leaky interface or abstraction. I see this pattern _a lot_ in this patch, so wondering you have thoughts about it." +63,"@@ -164,10 +164,13 @@ func WriteWordpressConfig(wordpressConfig *WordpressConfig, filePath string) err + return err + } + +- // Ensure target directory is writable. ++ // Ensure target directory exists and is writeable + dir := filepath.Dir(filePath) +- err = os.Chmod(dir, 0755) +- if err != nil { ++ if err = os.Chmod(dir, 0755); os.IsNotExist(err) { ++ if err = os.MkdirAll(dir, 0755); err != nil { ++ return err ++ } ++ } else if err != nil { + return err + } + ",This seems like an improved pattern :) +64,"@@ -127,16 +127,16 @@ class UserController < ApplicationController + # valid OpenID and one the user has control over before saving + # it as a password equivalent for the user. + session[:new_user_settings] = params +- openid_verify(params[:user][:openid_url], @user) ++ federated_verify(params[:user][:openid_url], @user) + else + update_user(@user, params) + end +- elsif using_open_id? ++ elsif using_federated_login? + # The redirect from the OpenID provider reenters here + # again and we need to pass the parameters through to + # the open_id_authentication function + settings = session.delete(:new_user_settings) +- openid_verify(nil, @user) do |user| ++ federated_verify(nil, @user) do |user| + update_user(user, settings) + end + end","`open_id_authentication` is no longer the name of the function, and it's not OpenID specific" +65,"@@ -243,10 +243,10 @@ void rai_qt::accounts::refresh_wallet_balance () + balance = balance + (this->wallet.node.ledger.account_balance (transaction, key)); + pending = pending + (this->wallet.node.ledger.account_pending (transaction, key)); + } +- auto final_text (std::string (""Wallet balance (XRB): "") + wallet.format_balance (balance)); ++ auto final_text (std::string (""Balance: "") + wallet.format_balance (balance)); + if (!pending.is_zero ()) + { +- final_text += ""\nWallet pending: "" + wallet.format_balance (pending); ++ final_text += ""\nPending: "" + wallet.format_balance (pending); + } + wallet_balance_label->setText (QString (final_text.c_str ())); + this->wallet.node.alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (60), [this]() {",This didn't require corresponding changes to the test case(s)? +66,"@@ -509,6 +509,7 @@ type TaskConfig struct { + Count Count `yaml:""count""` + ExecuteCommand ExecuteCommand `yaml:""exec""` + Variables map[string]string `yaml:""variables""` ++ EnvFile string `yaml:""env_file""` + Secrets map[string]string `yaml:""secrets""` + Storage Storage `yaml:""storage""` + }","A question! I think `string` totally works, but what do you think of `*string` for consistency?" +67,"@@ -25,6 +25,12 @@ import ( + metav1 ""k8s.io/apimachinery/pkg/apis/meta/v1"" + ) + ++const ( ++ AnnotationClusterInfrastructureReady = ""aws.cluster.sigs.k8s.io/infrastructure-ready"" ++ AnnotationControlPlaneReady = ""aws.cluster.sigs.k8s.io/control-plane-ready"" ++ ValueReady = ""true"" ++) ++ + // AWSResourceReference is a reference to a specific AWS resource by ID, ARN, or filters. + // Only one of ID, ARN or Filters may be specified. Specifying more than one will result in + // a validation error.",Should this be: `aws.infrastructure.cluster.sigs.k8s.io` instead? +68,"@@ -142,7 +142,7 @@ void PairLubricate::compute(int eflag, int vflag) + Ef[2][2] = h_rate[2]/domain->zprd; + Ef[0][1] = Ef[1][0] = 0.5 * h_rate[5]/domain->yprd; + Ef[0][2] = Ef[2][0] = 0.5 * h_rate[4]/domain->zprd; +- Ef[1][2] = Ef[2][1] = 0.5 * h_rate[3]/domain->zprd; ++ Ef[1][2] = Ef[2][1] = 0.5 * h_rate[3]/domain->xprd; + + // copy updated velocity/omega/angmom to the ghost particles + // no need to do this if not shearing since comm->ghost_velocity is set",Not clear on why this change is correct. +69,"@@ -193,5 +193,10 @@ public final class ByteBuffersIndexInput extends IndexInput implements RandomAcc + if (in == null) { + throw new AlreadyClosedException(""Already closed.""); + } +- } ++ } ++ ++ @Override ++ public boolean isMMapped() { ++ return true; ++ } + }","Hi Simon. Whether this should return true depends on what byte buffers are used? The same applies to ByteBufferIndexInput, actually... I don't think you can generally tell whether the ByteBuffers the input operates on come from a mmap call or from somewhere else (even direct buffers don't have to be a result of mmap)." +70,"@@ -54,6 +54,7 @@ storiesOf( 'PageSpeed Insights Module/Settings', module ) + decorators: [ + withRegistry, + ], ++ padding: 0, + } ) + .add( 'View, open with all settings', ( args, { registry } ) => { + return ;",All stories in this file also need to have the default padding. +71,"@@ -804,8 +804,10 @@ static void subsurface_handle_place_above(struct wl_client *client, + return; + } + ++ assert(sibling->parent == subsurface->parent); ++ + wl_list_remove(&subsurface->parent_pending_link); +- wl_list_insert(&sibling->parent_pending_link, ++ wl_list_insert(sibling->parent_pending_link.prev, + &subsurface->parent_pending_link); + + subsurface->reordered = true;","I don't think these asserts are necessary, because `subsurface_find_sibling` already searches in the parent. Or am I missing something?" +72,"@@ -0,0 +1,15 @@ ++class Episode < ActiveRecord::Base ++ attr_accessible :title, :duration, :file, :description, :published_on, :notes, ++ :old_url, :file_size ++ ++ validates_presence_of :title, :duration, :file, :file_size, :description, ++ :published_on ++ ++ def self.published ++ where(""published_on <= ?"", Date.today).order('published_on desc') ++ end ++ ++ def full_title ++ ""Episode #{id}: #{title}"" ++ end ++end",Should this be `number` instead of `id`? +73,"@@ -1569,12 +1569,11 @@ NATable *BindWA::getNATable(CorrName& corrName, + ((QualifiedName&)(table->getTableName())).setIsVolatile(TRUE); + } + +- // For now, do not allow access through the Trafodion external name created for +- // the HIVE object unless the inDDL flag is set. inDDL is set for drop +- // table and SHOWDDL statements. +- // TDB - may want to merge the Trafodion version with the HIVE version. +- // TDB - similar operation may be needed for external HBase tables +- if ((table) && (table->isExternalTable() && (! bindWA->inDDL()))) ++ // For now, don't allow access through the Trafodion external name created for ++ // native HIVE or HBASE objects unless the allowExternalTables flag is set. ++ // allowExternalTables is set for drop table and SHOWDDL statements. ++ // TDB - may want to merge the Trafodion version with the native version. ++ if ((table) && (table->isExternalTable() && (! bindWA->allowExternalTables()))) + { + *CmpCommon::diags() << DgSqlCode(-4258) + << DgTableName(table->getTableName().getQualifiedNameAsAnsiString());","I have forgotten why we thought this restriction is necessary. A user registers a Hive/HBase table with us but is not able to use the table with the registered name in DML. Will UPDATE STATs will be on the original name too (and update stats code will find out registered name and use it for Table_uid?). This was the registration concept is almost like an internal implementation idea, at some point could even be done by some utility program for all existing Hive/hBase tables, and the user need not be aware of it? I am struggling with a user would want to register a table, if they cannot use it by that name." +74,"@@ -40,6 +40,18 @@ + + struct ase_cfg_t *cfg; + ++int app2sim_alloc_rx; // app2sim mesaage queue in RX mode ++int sim2app_alloc_tx; // sim2app mesaage queue in TX mode ++int app2sim_mmioreq_rx; // MMIO Request path ++int sim2app_mmiorsp_tx; // MMIO Response path ++int app2sim_umsg_rx; // UMSG message queue in RX mode ++int app2sim_portctrl_req_rx; // Port Control messages in Rx mode ++int app2sim_dealloc_rx; ++int sim2app_dealloc_tx; ++int sim2app_portctrl_rsp_tx; ++int sim2app_intr_request_tx; ++int intr_event_fds[MAX_USR_INTRS]; ++ + int glbl_test_cmplt_cnt; // Keeps the number of session_deinits received + + volatile int sockserver_kill;",Should most of these non-globals be static? +75,"@@ -14,6 +14,14 @@ class TestFakerName < Test::Unit::TestCase + assert @tester.name_with_middle.match(/(\w+\.? ?){3,4}/) + end + ++ def test_first_name ++ assert @tester.first_name.match(/(\w+\.? ?){3,4}/) ++ end ++ ++ def test_last_name ++ assert @tester.last_name.match(/(\w+\.? ?){3,4}/) ++ end ++ + def test_prefix + assert @tester.prefix.match(/[A-Z][a-z]+\.?/) + end",Please do not approve PRs without tests!!!! +76,"@@ -48,7 +48,7 @@ class WebEngineView(QWebEngineView): + else: + profile = webenginesettings.default_profile + page = WebEnginePage(theme_color=theme_color, profile=profile, +- parent=self) ++ parent=self, win_id=win_id) + self.setPage(page) + + def shutdown(self):",Now that you handle this in `webenginetab.py` you can undo all the changes in this file. +77,"@@ -30,7 +30,11 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext + public class JavaFXApplication extends Application { + + public static void main(String[] args) { +- Application.launch(JavaFXApplication.class); ++ try { ++ Application.launch(JavaFXApplication.class); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ } + } + + @Override",I think we should log the exception to a log file instead of printing it. The current behavior (not catching the exception) should lead to an automatic print of the exception to the terminal/console. +78,"@@ -57,7 +57,7 @@ func (r *Helper) Apply(obj []byte) (ApplyResult, error) { + if err != nil { + r.logger.WithError(err). + WithField(""stdout"", ioStreams.Out.(*bytes.Buffer).String()). +- WithField(""stderr"", ioStreams.ErrOut.(*bytes.Buffer).String()).Error(""running the apply command failed"") ++ WithField(""stderr"", ioStreams.ErrOut.(*bytes.Buffer).String()).Warn(""running the apply command failed"") + return """", err + } + return changeTracker.GetResult(), nil","These changes to the resource helpers have some more far-reaching implications as they also affect calls made in hive-operator, I believe. It's probably OK still, though. Ideally, the resource helper would not be the one doing the logging, since it cannot know the severity, but that is well beyond something that we should tackle for this PR. I would rather have the hive-operator log warnings than have the syncsetinstance controller log errors." +79,"@@ -167,7 +167,7 @@ class ExportCategoryTableMap extends TableMap + */ + public function buildRelations() + { +- $this->addRelation('Export', '\\Thelia\\Model\\Export', RelationMap::ONE_TO_MANY, array('id' => 'export_category_id', ), 'CASCADE', 'RESTRICT', 'Exports'); ++ $this->addRelation('Export', '\\Thelia\\Model\\Export', RelationMap::ONE_TO_MANY, array('id' => 'export_category_id', ), null, null, 'Exports'); + $this->addRelation('ExportCategoryI18n', '\\Thelia\\Model\\ExportCategoryI18n', RelationMap::ONE_TO_MANY, array('id' => 'id', ), 'CASCADE', null, 'ExportCategoryI18ns'); + } // buildRelations() + ",do you really want to change the behavior on foreign key ? +80,"@@ -183,7 +183,8 @@ void event_batch_destroy (struct event_batch *batch) + if (batch->f) + (void)flux_future_wait_for (batch->f, -1); + if (batch->state_trans) { +- event_publish_state (batch->event, batch->state_trans); ++ if (json_array_size (batch->state_trans) > 0) ++ event_publish_state (batch->event, batch->state_trans); + json_decref (batch->state_trans); + } + if (batch->responses) {",Looks like my bad. Thanks for fixing! +81,"@@ -82,6 +82,7 @@ class Command: + no_cmd_split: If true, ';;' to split sub-commands is ignored. + backend: Which backend the command works with (or None if it works with + both) ++ no_replace_variables: Whether or not to replace variables like {url} + _qute_args: The saved data from @cmdutils.argument + _needs_js: Whether the command needs javascript enabled + _modes: The modes the command can be executed in.","I think ""Don't replace variables ..."" would be cleaner." +82,"@@ -82,8 +82,7 @@ class MPLPlot(DimensionedPlot): + sublabel_size = param.Number(default=18, doc="""""" + Size of optional subfigure label."""""") + +- projection = param.ObjectSelector(default=None, +- objects=['3d', 'polar', None], doc="""""" ++ projection = param.Parameter(default=None, doc="""""" + The projection of the plot axis, default of None is equivalent to + 2D plot, '3d' and 'polar' are also supported."""""") + ",Do you validate the possible strings? I've not read the code below but we should make sure if a string is supplied it is validate... +83,"@@ -40,13 +40,11 @@ func AddDiskImportSteps(w *daisy.Workflow, dataDiskInfos []ovfutils.DiskInfo) { + for i, dataDiskInfo := range dataDiskInfos { + dataDiskIndex := i + 1 + dataDiskFilePath := dataDiskInfo.FilePath +- diskNames = append( +- diskNames, +- fmt.Sprintf(""%v-data-disk-%v"", w.Vars[""instance_name""].Value, dataDiskIndex)) ++ diskNames = append(diskNames, generateDataDiskName(w.Vars[""instance_name""].Value, dataDiskIndex)) + + setupDataDiskStepName := fmt.Sprintf(""setup-data-disk-%v"", dataDiskIndex) +- diskImporterDiskName := fmt.Sprintf(""disk-importer-%v"", dataDiskIndex) +- scratchDiskDiskName := fmt.Sprintf(""disk-importer-scratch-%v-%v"", dataDiskIndex, w.Vars[""instance_name""].Value) ++ diskImporterDiskName := fmt.Sprintf(""disk-importer-%v-%v"", dataDiskIndex, w.ID()) ++ scratchDiskDiskName := fmt.Sprintf(""disk-importer-scratch-%v-%v"", dataDiskIndex, w.ID()) + + setupDataDiskStep := daisy.NewStepDefaultTimeout(setupDataDiskStepName, w) + setupDataDiskStep.CreateDisks = &daisy.CreateDisks{",I'd recommend using generateDataDiskName here as well -- might as well benefit from the safety that it gives to protect yourself from future changes to w.ID(). +84,"@@ -29,6 +29,11 @@ import java.util.Map; + * @param the concrete Java class of a ContentFile instance. + */ + public interface ContentFile { ++ /** ++ * Returns the ordinal position of the file in a manifest, or null if it was not read from a manifest. ++ */ ++ Long pos(); ++ + /** + * Returns id of the partition spec used for partition metadata. + */",qq: do we want to include anything in the name to indicate that it is a position in the manifest? +85,"@@ -969,8 +969,11 @@ public class VRBrowserActivity extends PlatformActivity implements WidgetManager + GleanMetricsService.stopImmersive(); + Handler handler = new Handler(Looper.getMainLooper()); + handler.postDelayed(() -> { +- mWindows.resumeCompositor(); +- Log.d(LOGTAG, ""Compositor Resumed""); ++ if (!mWindows.isPaused()) { ++ Log.d(LOGTAG, ""Compositor resume begin""); ++ mWindows.resumeCompositor(); ++ Log.d(LOGTAG, ""Compositor resume end""); ++ } + }, 20); + } + ",These logs should probably use the `LOGTAG` +86,"@@ -28,10 +28,10 @@ import ( + ""github.com/mysteriumnetwork/node/core/connection"" + ""github.com/mysteriumnetwork/node/services/wireguard"" + ""github.com/mysteriumnetwork/node/services/wireguard/key"" +- ""github.com/mysteriumnetwork/wireguard-go/device"" +- ""github.com/mysteriumnetwork/wireguard-go/tun"" + ""github.com/pkg/errors"" + ""github.com/rs/zerolog/log"" ++ ""golang.zx2c4.com/wireguard/device"" ++ ""golang.zx2c4.com/wireguard/tun"" + ) + + const (","From this, it was clear, that we are using our version of wireguard-go. And now it looks like we are using original packages which is confusing." +87,"@@ -43,7 +43,7 @@ namespace Nethermind.JsonRpc + + public static ResultWrapper Fail(Exception e) + { +- return new() { Result = Result.Fail(e.ToString()), ErrorCode = ErrorCodes.InternalError}; ++ return new() { Result = Result.Fail(e.Message), ErrorCode = ErrorCodes.InternalError}; + } + + public static ResultWrapper Fail(string error, int errorCode, T outputData)",Any particular reason for this? This potentially will make harder to investigate users issues +88,"@@ -999,7 +999,8 @@ Blockly.BlockSvg.prototype.updatePreviews = function(closestConnection, + // grayed-out blocks instead of highlighting the connection; for compatibility + // with Web Blockly the name ""highlightedConnection"" will still be used. + if (Blockly.highlightedConnection_ && +- Blockly.highlightedConnection_ != closestConnection) { ++ (Blockly.highlightedConnection_ != closestConnection || ++ Blockly.localConnection_ != localConnection)) { + if (Blockly.insertionMarker_ && Blockly.insertionMarkerConnection_) { + Blockly.BlockSvg.disconnectInsertionMarker(); + }",Do you also need to check if Blockly.localConnection_ is non-null? +89,"@@ -1,5 +1,6 @@ + module RSpec + module Core ++ # Internal container for global non-configuration data + class World + + include RSpec::Core::Hooks","Not really a container, and it's not just about non-config data, not sure of a better description, @myronmarston ?" +90,"@@ -3,6 +3,8 @@ const { basename } = require('./path-utils'); + const shim = require('./shim').default; + const JoplinError = require('./JoplinError').default; + const { Buffer } = require('buffer'); ++const { Readable } = require('stream').Readable; ++const { GetObjectCommand, ListObjectsV2Command, HeadObjectCommand, PutObjectCommand, DeleteObjectCommand, DeleteObjectsCommand } = require(""@aws-sdk/client-s3""); + + const S3_MAX_DELETES = 1000; + ","The desktop app will load this fine. on iOS I get `TypeError: undefined is not an object (evaluating '_$$_REQUIRE(_dependencyMap[8], ""stream"").Readable.Readable')` if I change it to `const Readable = require('stream').Readable;` or `const { Readable } = require('stream');` I get undefined errors from the stream on iOS: `[TypeError: stream.on is not a function. (In 'stream.on(""data"", function (chunk) { return chunks.push(chunk); })', 'stream.on' is undefined)]` What am I missing?" +91,"@@ -93,7 +93,9 @@ func (m *MockStorer) Put(ctx context.Context, mode storage.ModePut, chs ...swarm + po := swarm.Proximity(ch.Address().Bytes(), m.baseAddress) + m.bins[po]++ + } +- m.store[ch.Address().String()] = ch.Data() ++ b := make([]byte, len(ch.Data())) ++ copy(b, ch.Data()) ++ m.store[ch.Address().String()] = b + m.modePut[ch.Address().String()] = mode + + // pin chunks if needed","this is needed since the chunk feeder shares memory across calls to the pipeline. this is in order to avoid multiple allocations. this change mimics the behavior of shed and localstore, and copies the data from the call into the in-memory store" +92,"@@ -42,6 +42,10 @@ import ( + ""go.uber.org/yarpc/yarpcerrors"" + ) + ++func init() { ++ opentracing.SetGlobalTracer(nil) ++} ++ + func TestHandlerSuccess(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish()",wut. We can do this at the beginning of tests if we want right? Why are we depending on init? +93,"@@ -1403,9 +1403,12 @@ func (c *client) processConnect(arg []byte) error { + c.mu.Lock() + acc := c.acc + c.mu.Unlock() ++ srv.mu.Lock() + if acc != nil && acc != srv.gacc { ++ srv.mu.Unlock() + return ErrTooManyAccountConnections + } ++ srv.mu.Unlock() + } + c.authViolation() + return ErrAuthentication",Same trick here IMO. +94,"@@ -108,10 +108,11 @@ module Selenium + + def initialize(source, duration, x, y, element: nil, origin: nil) + super(source) ++ + @duration = duration * 1000 + @x_offset = x + @y_offset = y +- @origin = element || origin ++ @origin = origin || POINTER + end + + def type",Should be `@origin = element || origin || POINTER` +95,"@@ -50,11 +50,14 @@ func NewUpgradeCStorSPCJob() *cobra.Command { + Long: cstorSPCUpgradeCmdHelpText, + Example: `upgrade cstor-spc --spc-name `, + Run: func(cmd *cobra.Command, args []string) { ++ util.CheckErr(options.RunCStorSPCUpgradeChecks(cmd, args), util.Fatal) + options.resourceKind = ""storagePoolClaim"" +- util.CheckErr(options.RunPreFlightChecks(cmd), util.Fatal) +- util.CheckErr(options.RunCStorSPCUpgradeChecks(cmd), util.Fatal) +- util.CheckErr(options.InitializeDefaults(cmd), util.Fatal) +- util.CheckErr(options.RunCStorSPCUpgrade(cmd), util.Fatal) ++ if options.cstorSPC.spcName != """" { ++ singleCstorSPCUpgrade(cmd) ++ } ++ if len(args) != 0 { ++ bulkCstorSPCUpgrade(cmd, args) ++ } + }, + } + ",this example needs a fix? +96,"@@ -248,9 +248,9 @@ static void close(struct roots_view *view) { + struct wlr_xdg_surface *surface = view->xdg_surface; + struct wlr_xdg_popup *popup = NULL; + wl_list_for_each(popup, &surface->popups, link) { +- wlr_xdg_surface_send_close(popup->base); ++ wlr_xdg_popup_destroy(popup->base); + } +- wlr_xdg_surface_send_close(surface); ++ wlr_xdg_toplevel_send_close(surface); + } + + static void destroy(struct roots_view *view) {",Is it safe to assume this surface is a toplevel? +97,"@@ -225,6 +225,16 @@ projCtx pj_ctx_alloc() + return new (std::nothrow) projCtx_t(*pj_get_default_ctx()); + } + ++/************************************************************************/ ++/* pj_ctx_clone() */ ++/************************************************************************/ ++ ++projCtx pj_ctx_clone( projCtx ctx ) ++ ++{ ++ return new (std::nothrow) projCtx_t(*ctx); ++} ++ + /************************************************************************/ + /* pj_ctx_free() */ + /************************************************************************/",we don't need that function +98,"@@ -72,6 +72,13 @@ public enum Platform { + } + }, + ++ WIN10(""windows 10"", ""win10"") { ++ @Override ++ public Platform family() { ++ return WINDOWS; ++ } ++ }, ++ + MAC(""mac"", ""darwin"", ""os x"") {}, + + SNOW_LEOPARD(""snow leopard"", ""os x 10.6"") {","we'll also have to think about adding ""Windows Server 2014"" or whatever they come up with later." +99,"@@ -35,6 +35,9 @@ public interface ExecutorLoader { + Map> fetchActiveFlows() + throws ExecutorManagerException; + ++ Pair fetchActiveFlowByExecId(int execId) ++ throws ExecutorManagerException; ++ + List fetchFlowHistory(int skip, int num) + throws ExecutorManagerException; + ",curious do we have an API to fetch an inactive flow? +100,"@@ -116,10 +116,6 @@ function upgradeToVNodes(arr, offset) { + if (Array.isArray(obj)) { + upgradeToVNodes(obj); + } +- else if (obj && typeof obj==='object' && !isValidElement(obj) && ((obj.props && obj.type) || obj.text!=null)) { +- if (obj.text) continue; +- arr[i] = createElement(obj.type, obj.props, obj.props.children); +- } + } + } + ",This branch is not needed anymore because every `vnode` that passes through `h` in compat or core will have the `$$typeof`-property now . +101,"@@ -0,0 +1,16 @@ ++const { getComposedParent } = axe.commons.dom; ++ ++function shouldMatchElement(el) { ++ if (!el) { ++ return true; ++ } ++ const ariaHiddenValue = el.getAttribute('aria-hidden') ++ ? el.getAttribute('aria-hidden') ++ : null; ++ if (ariaHiddenValue === null) { ++ return shouldMatchElement(getComposedParent(el)); ++ } ++ return false; ++} ++ ++return shouldMatchElement(getComposedParent(node));",Did you mean to use `hasAttribute`? You shouldn't. This does not improve performance and it messes with the readability. +102,"@@ -37,13 +37,14 @@ import pytest + import py.path # pylint: disable=no-name-in-module + + import helpers.stubs as stubsmod ++from helpers.utils import CallbackChecker + from qutebrowser.config import config, configdata, configtypes, configexc + from qutebrowser.utils import objreg, standarddir + from qutebrowser.browser.webkit import cookies + from qutebrowser.misc import savemanager, sql + from qutebrowser.keyinput import modeman + +-from PyQt5.QtCore import pyqtSignal, QEvent, QSize, Qt, QObject ++from PyQt5.QtCore import QEvent, QSize, Qt + from PyQt5.QtGui import QKeyEvent + from PyQt5.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout + from PyQt5.QtNetwork import QNetworkCookieJar",Please import modules and not classes (except for Qt stuff). +103,"@@ -20,6 +20,11 @@ public class DummyJavaNode extends AbstractJavaNode { + super(id); + } + ++ @Override ++ public void setImage(String image) { ++ super.setImage(image); ++ } ++ + @Override + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return data;","Hm... why do we have a ""DummyJavaNode"" in src/main? Looks like, this should have gone into src/test...." +104,"@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and + limitations under the License. + */ + ++// Package v1alpha1 + package v1alpha1 + + // CasKey is used for all cas specific annotation keys",This seems meaningless. If we cannot add any info let us remove this. +105,"@@ -493,6 +493,14 @@ func (c *Container) GetLabels() map[string]string { + return c.labels + } + ++// GetPorts gets the ports for a container ++func (c *Container) GetPorts() []PortBinding { ++ c.lock.RLock() ++ defer c.lock.RUnlock() ++ ++ return c.Ports ++} ++ + // HealthStatusShouldBeReported returns true if the health check is defined in + // the task definition + func (c *Container) HealthStatusShouldBeReported() bool {",Can you rename `Ports` to `PortsUnsafe`? +106,"@@ -0,0 +1,10 @@ ++module ReturnToHelper ++ def make_return_to(name, path) ++ sig = OpenSSL::HMAC.digest( ++ OpenSSL::Digest::SHA256.new, ++ Rails.application.secrets.secret_key_base, ++ name + ""$"" + path ++ ) ++ {name: name, path: path, sig: Base64.urlsafe_encode64(sig)} ++ end ++end",This feels like it could be moved out to your first gem! +107,"@@ -44,7 +44,7 @@ public abstract class NewSessionQueue implements HasReadyState { + + public abstract boolean offerFirst(HttpRequest request, RequestId requestId); + +- public abstract Optional poll(); ++ public abstract Optional poll(RequestId requestId); + + public abstract int clear(); + ","The expected behaviour for `poll` would be to match what `Deque` does, which is: > Retrieves and removes the head of the queue represented by this deque As such, you shouldn't need the `RequestId` here." +108,"@@ -7,4 +7,17 @@ + axe.utils.toArray = function (thing) { + 'use strict'; + return Array.prototype.slice.call(thing); +-}; ++}; ++ ++ ++/** ++ * Creates an array without duplicate values from 2 array inputs ++ * @param {Array} arr1 First array ++ * @param {Array} arr2 Second array ++ * @return {Array} ++ */ ++axe.utils.uniqueArray = (arr1, arr2) => { ++ return arr1.concat(arr2).filter((elem, pos, arr) => { ++ return arr.indexOf(elem) === pos; ++ }); ++};","This is super minor, but it'd be nice if this iterated over an arbitrary number of array inputs." +109,"@@ -1676,9 +1676,10 @@ _tmain(int argc, TCHAR *targv[]) + } + # ifdef UNIX + /* i#1676: detect whether under gdb */ +- _snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), ""/proc/%d/exe"", getppid()); +- NULL_TERMINATE_BUFFER(buf); +- i = readlink(buf, buf, BUFFER_SIZE_ELEMENTS(buf)); ++ char path_buf[MAXIMUM_PATH]; ++ _snprintf(path_buf, BUFFER_SIZE_ELEMENTS(path_buf), ""/proc/%d/exe"", getppid()); ++ NULL_TERMINATE_BUFFER(path_buf); ++ i = readlink(path_buf, buf, BUFFER_SIZE_ELEMENTS(buf)); + if (i > 0) { + if (i < BUFFER_SIZE_ELEMENTS(buf)) + buf[i] = '\0';","What is the problem here? The commit message has strange wording ""readlink is defined with restrict pointers"": do you mean ""restricted""? Is that a well-defined language term? I'm not sure what it means." +110,"@@ -17,6 +17,7 @@ package com.google.api.codegen.util.ruby; + import com.google.api.codegen.util.Name; + import com.google.api.codegen.util.NameFormatter; + import com.google.api.codegen.util.NamePath; ++import com.google.common.collect.ImmutableSet; + + /** + * The NameFormatter for Ruby.",Why are we not wrapping here? +111,"@@ -2,12 +2,10 @@ + + namespace Shopsys\FrameworkBundle\Model\Product\Filter; + +-use Shopsys\FrameworkBundle\Model\Product\Parameter\Parameter; +- + class ParameterFilterData + { + /** +- * @var \Shopsys\FrameworkBundle\Model\Product\Parameter\Parameter ++ * @var \Shopsys\FrameworkBundle\Model\Product\Parameter\Parameter|null + */ + public $parameter; + ","I though that all data objects are being unified in the fashion where all default values are initialized in constructor, are not they?" +112,"@@ -22,16 +22,16 @@ var sourceHashes = map[string]string{ + ""libflux/flux-core/src/ast/flatbuffers/mod.rs"": ""00c75dc1da14487953a4a017616fb8a237fe3da437c876f1328532dd7906f015"", + ""libflux/flux-core/src/ast/flatbuffers/monotype.rs"": ""4e82aae8e7edb8e230302241fe702ece9ae84fc708003c24709c2ea944cfaae8"", + ""libflux/flux-core/src/ast/flatbuffers/tests.rs"": ""ea85b78049f0c3d79daedcf9e171ccb00d0a596d1a643aa218590c99e6b160bc"", +- ""libflux/flux-core/src/ast/mod.rs"": ""676e22d24cd7a97525688ed391a980d08b4bee40c5b5067d187f3ae6d66210ca"", ++ ""libflux/flux-core/src/ast/mod.rs"": ""29b25b75a01cf1e1ac2b52d99b91986cec32011dc55af1ffd7f145838fce858d"", + ""libflux/flux-core/src/ast/tests.rs"": ""bc7f77d569d8bbd4b9d00653f48bacd47eed46f53024dce836d3c8bbb6a80555"", + ""libflux/flux-core/src/ast/walk/mod.rs"": ""e8a03023d7426bcf6dfdb1a61ac3263f5cf9194a595a1584dff7c899d06562f1"", + ""libflux/flux-core/src/ast/walk/tests.rs"": ""f7b2d7dd5643bb795a86c04b6979b136b0de46b52b213caff094aed6d204a05d"", + ""libflux/flux-core/src/formatter/mod.rs"": ""945736a4ad87adb6a3f359b6f2da6e5492b3cb0efd282e277303e2acae137763"", + ""libflux/flux-core/src/formatter/tests.rs"": ""b0a10998a65fc4b54a8f68b3a0ed186d8548ba3d7638f911eb188d2ce485206f"", + ""libflux/flux-core/src/lib.rs"": ""d19b7054e07f234c107d457030a0031374c123fe14a84a5b8e35537d138bac7a"", +- ""libflux/flux-core/src/parser/mod.rs"": ""e3f11fe29f47271b5c04accc2d7efa35e1dc62c6de036bf0cc0cccda5e4742e8"", ++ ""libflux/flux-core/src/parser/mod.rs"": ""daf24b2c439f4c7a6f138e2b25064a205aee73bb6cffc898df22dd0c962ca5df"", + ""libflux/flux-core/src/parser/strconv.rs"": ""748c82f6efc2eafaafb872db5b4185ce29aafa8f03ba02c4b84f4a9614e832d2"", +- ""libflux/flux-core/src/parser/tests.rs"": ""e3a7c9222f90323a7ea9b319bd84f96f66c6f115af6d199a0da332c894713ae4"", ++ ""libflux/flux-core/src/parser/tests.rs"": ""43a1e5d3de85d76da2107544e417f583a1f66c20910286285b9645a309c42425"", + ""libflux/flux-core/src/scanner/mod.rs"": ""2e15c9e0a73d0936d2eaeec030b636786db6dbe7aab673045de3a3e815c49f8a"", + ""libflux/flux-core/src/scanner/scanner.rl"": ""530c062363b66daded3c521af44111b99ffee0eeb2a12ccffa8b8f349002d852"", + ""libflux/flux-core/src/scanner/scanner_generated.rs"": ""d65dcc216ccbb88d8f2e261a994ba2789075e434cb7a0f5e39e390bee2821e5b"",",Does this file actually need to be committed to git? Having to run `make generate` is rather tedious on each PR and it conflicts easily. +113,"@@ -440,18 +440,6 @@ func parseConfig(loc location.Location, opts options.Options) (interface{}, erro + cfg.ProjectID = os.Getenv(""GOOGLE_PROJECT_ID"") + } + +- if cfg.JSONKeyPath == """" { +- if path := os.Getenv(""GOOGLE_APPLICATION_CREDENTIALS""); path != """" { +- // Check read access +- if _, err := ioutil.ReadFile(path); err != nil { +- return nil, errors.Fatalf(""Failed to read google credential from file %v: %v"", path, err) +- } +- cfg.JSONKeyPath = path +- } else { +- return nil, errors.Fatal(""No credential file path is set"") +- } +- } +- + if err := opts.Apply(loc.Scheme, &cfg); err != nil { + return nil, err + }","We don't need this anymore, as Google's library handles various auth mechanisms for us. We'll be less explicit about why we're failing but we gain support for several authentication methods- swings and roundabouts!" +114,"@@ -1,11 +1,12 @@ + package plugin + + type Config struct { +- SocketPath string `yaml:""path""` +- Volumes VolumesConfig `yaml:""volume""` ++ SocketDir string `yaml:""socket_dir"" default:""/run/docker/plugins""` ++ Volumes VolumesConfig `yaml:""volume""` ++ GPUs map[string]map[string]string `yaml:""GPUs""` + } + + type VolumesConfig struct { +- Root string ++ Root string `yaml:""root"" default:""/var/lib/docker-volumes""` + Volumes map[string]map[string]string + }",No need to speficy attribute here. Moreover in yaml it is default to use lowercase names. +115,"@@ -8,10 +8,12 @@ using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; ++using System.Linq; + using System.Net; + using System.Net.Http; + using System.Text; + using System.Threading; ++using System.Threading.Tasks; + using Task = System.Threading.Tasks.Task; + + namespace Microsoft.DotNet.Build.CloudTestTasks",In general I'm a trying to understand the reason behind this PR. Looks like if a blob (name) already exists we check if the contents are identical? In what scenarios this is not the case? When we want to publish a package/asset that has changed but still we want to use the same version? +116,"@@ -151,7 +151,9 @@ class BlacklistRuleBook(bre.BaseRuleBook): + lists: first one is IP addresses, + second one is network blocks + """""" +- data = urllib2.urlopen(url).read() ++ req = urllib2.build_opener() ++ req.addheaders = [('User-Agent', 'Forseti blacklist rules engine agent')] ++ data = req.open(url).read() + ip_addresses = re.findall(r'^[0-9]+(?:\.[0-9]+){3}$', data, re.M) + netblocks = re.findall(r'^[0-9]+(?:\.[0-9]+){0,3}/[0-9]{1,2}$', + data, re.M)","Can rename `req` to be `opener`, since that is the object, and it wraps `req` internally?" +117,"@@ -1405,6 +1405,8 @@ def getFormatFieldSpeech(attrs,attrsCache=None,formatConfig=None,unit=None,extra + linePrefix=attrs.get(""line-prefix"") + if linePrefix: + textList.append(linePrefix) ++ breakpoint=attrs.get(""breakpoint"") ++ if breakpoint: textList.append(breakpoint) + if attrsCache is not None: + attrsCache.clear() + attrsCache.update(attrs)","@MichaelDCurran, thoughts on adding a breakpoint format field attribute? It seems almost app specific, but I guess it does seem odd abusing line-prefix. Is there any more generic concept here?" +118,"@@ -539,7 +539,10 @@ class WebElement(object): + @property + def rect(self): + """"""A dictionary with the size and location of the element."""""" +- return self._execute(Command.GET_ELEMENT_RECT)['value'] ++ if self._w3c: ++ return self._execute(Command.GET_ELEMENT_RECT)['value'] ++ else: ++ return self.size, self.location + + @property + def screenshot_as_base64(self):",This would return a tuple of two dictionaries. You need to combine them and return a dictionary +119,"@@ -7,10 +7,14 @@ import ( + ""errors"" + ""fmt"" + ++ ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/archer"" ++ ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/manifest"" ++ ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/store/secretsmanager"" + ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/store/ssm"" + ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/term/color"" + ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/term/log"" + ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/term/prompt"" ++ ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/workspace"" + + ""github.com/spf13/cobra"" + )","What do you think of moving the example to the help text of the prompt? and the prompt itself can be ""What is your application's GitHub repository URL?""" +120,"@@ -58,9 +58,12 @@ public class TracerTest { + public void shouldBeAbleToCreateATracer() { + List allSpans = new ArrayList<>(); + Tracer tracer = createTracer(allSpans); ++ long timeStamp = 1593493828L; + + try (Span span = tracer.getCurrentContext().createSpan(""parent"")) { + span.setAttribute(""cheese"", ""gouda""); ++ span.addEvent(""Grating cheese""); ++ span.addEvent(""Melting cheese"", timeStamp); + span.setStatus(Status.NOT_FOUND); + } + ",Break out tests for events into their own tests rather than placing them in other ones. That makes it easier for us to figure out where problems lie and to do a TDD-driven implementation over new APIs. +121,"@@ -266,7 +266,7 @@ bool parse_it(Iterator &first, Iterator last, RDKit::RWMol &mol) { + } else { + if (!parse_atom_labels(first, last, mol)) return false; + } +- } else if ((first + 9) < last && ++ } else if (std::distance(first, last) > 9 && + std::string(first, first + 9) == ""atomProp:"") { + first += 9; + if (!parse_atom_props(first, last, mol)) return false;",Nice use of std::distance. I'm a bit worried about first += 9 though. +122,"@@ -578,8 +578,9 @@ func (c *Operator) syncNodeEndpoints(ctx context.Context) error { + ObjectMeta: metav1.ObjectMeta{ + Name: c.kubeletObjectName, + Labels: c.config.Labels.Merge(map[string]string{ +- ""k8s-app"": ""kubelet"", +- ""app.kubernetes.io/name"": ""kubelet"", ++ ""k8s-app"": ""kubelet"", ++ ""app.kubernetes.io/name"": ""kubelet"", ++ ""app.kubernetes.io/part-of"": ""prometheus-operator"", + }), + }, + Subsets: []v1.EndpointSubset{","Shouldn't this be `app.kubernetes.io/managed-by` as prometheus-operator manages this resource, but this resource isn't a part of prometheus-operator?" +123,"@@ -41,8 +41,9 @@ namespace Datadog.Trace.ClrProfiler + + if (parent != null && + parent.Type == SpanTypes.Http && +- parent.GetTag(Tags.HttpMethod).Equals(httpMethod, StringComparison.OrdinalIgnoreCase) && +- parent.GetTag(Tags.HttpUrl).Equals(UriHelpers.CleanUri(requestUri, removeScheme: false, tryRemoveIds: false), StringComparison.OrdinalIgnoreCase)) ++ parent.GetTag(Tags.InstrumentationName) != null && ++ httpMethod.Equals(parent.GetTag(Tags.HttpMethod), StringComparison.OrdinalIgnoreCase) && ++ UriHelpers.CleanUri(requestUri, removeScheme: false, tryRemoveIds: false).Equals(parent.GetTag(Tags.HttpUrl), StringComparison.OrdinalIgnoreCase)) + { + // we are already instrumenting this, + // don't instrument nested methods that belong to the same stacktrace","As long as we're being extra-vigilant about NREs, should we check that `httpMethod` and `requestUri` are not null?" +124,"@@ -19,6 +19,7 @@ import ( + ""github.com/iotexproject/iotex-core/cli/ioctl/cmd/node"" + ""github.com/iotexproject/iotex-core/cli/ioctl/cmd/update"" + ""github.com/iotexproject/iotex-core/cli/ioctl/cmd/version"" ++ xrc20 ""github.com/iotexproject/iotex-core/cli/ioctl/cmd/xrc20"" + ) + + // RootCmd represents the base command when called without any subcommands",No need to have `xrc20` alias +125,"@@ -172,6 +172,19 @@ def define_environment_cls(pipeline_def): + ) + + ++def context_cls_inst(pipeline_def): ++ check.inst_param(pipeline_def, 'pipeline_def', PipelineDefinition) ++ pipeline_name = camelcase(pipeline_def.name) ++ return SystemNamedDict( ++ name='{pipeline_name}.Context'.format(pipeline_name=pipeline_name), ++ fields={ ++ 'context': define_maybe_optional_selector_field( ++ define_context_context_cls(pipeline_name, pipeline_def.context_definitions) ++ ) ++ }, ++ ).inst() ++ ++ + def define_expectations_config_cls(name): + check.str_param(name, 'name') + ",the naming convention I'm been adopting if `_type` for instances of these classes. So maybe `context_config_type` is a better name for this fn +126,"@@ -54,6 +54,7 @@ public class BlockMiner> implements Runnabl + private final ProtocolSchedule protocolSchedule; + private final Subscribers observers; + private final AbstractBlockScheduler scheduler; ++ private Boolean gpuMining = false; + + public BlockMiner( + final Function blockCreatorFactory,","Don't call it GPU mining, call it `externalMining`, here and throughout." +127,"@@ -252,6 +252,15 @@ return [ + | folder - a folder prefix for storing all generated files inside. + | path - the public path relative to the application base URL, + | or you can specify a full URL path. ++ | ++ | For the 'media' resource you can also specify: ++ | ++ | imageMaxWidth - Resize all media manager image uploads to be ++ | within this with (in pixels, 0 = ignore) ++ | imageMaxHeight - Resize all media manager image uploads to be ++ | within this height (in pixels, 0 = ignore) ++ | imageQuality - Set this quality to all media manager image uploads ++ | (1-100) + */ + + 'storage' => [","`within this with` typo, should be `within this width`" +128,"@@ -22,10 +22,12 @@ import ( + ) + + // Prometheus defines a Prometheus deployment. ++// +k8s:openapi-gen=true + type Prometheus struct { + metav1.TypeMeta `json:"",inline""` + // Standard object’s metadata. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata ++ // +k8s:openapi-gen=false + metav1.ObjectMeta `json:""metadata,omitempty""` + // Specification of the desired behavior of the Prometheus cluster. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status",how come this is false? +129,"@@ -24,6 +24,19 @@ function node_require(module) { + return require(module); + } + ++function typeOf(obj) { ++ return ({}).toString.call(obj).match(/\s(\w+)/)[1].toLowerCase(); ++} ++ ++function checkTypes(args, types) { ++ args = [].slice.call(args); ++ for (var i = 0; i < types.length; ++i) { ++ if (typeOf(args[i]) !== types[i]) { ++ throw new TypeError('param ' + i + ' must be of type ' + types[i]); ++ } ++ } ++} ++ + const performFetch = typeof fetch === 'undefined' ? node_require('node-fetch') : fetch; + + const url_parse = require('url-parse');",How about `Object.prototype.toString`? Or using the `typeof` operator? +130,"@@ -83,6 +83,7 @@ type ReporterKBPKI struct { + notifySyncBuffer chan *keybase1.FSPathSyncStatus + suppressCh chan time.Duration + canceler func() ++ ctx context.Context + } + + // NewReporterKBPKI creates a new ReporterKBPKI.","I know @jzila suggested this, but I disagree: you're really not supposed to save a context in a struct. Can you get by with just saving the `Done()` channel instead? The `ctx` should continue to be passed around explicitly." +131,"@@ -12,12 +12,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking + { + IsWindows = PlatformApis.IsWindows; + +- var isDarwinMono = +-#if DNX451 +- IsWindows ? false : PlatformApis.IsDarwin; +-#else +- false; +-#endif ++ var isDarwinMono = !IsWindows && PlatformApis.IsDarwin; + + if (isDarwinMono) + {",This check isn't right though. +132,"@@ -96,6 +96,8 @@ public abstract class DynamicLangXApiView implements ViewModel { + return missingDefaultServiceAddress() || missingDefaultServiceScopes(); + } + ++ public abstract String codeGenVersion(); ++ + @Override + public String resourceRoot() { + return SnippetSetRunner.SNIPPET_RESOURCE_ROOT;","maybe `toolkitVersion` instead? It doesn't necessarily have to be called that in the generated code, but in the view model classes, I think it makes it clearer that it is the version of toolkit itself." +133,"@@ -230,15 +230,13 @@ module.exports = class XHRUpload extends Plugin { + const body = opts.getResponseData(xhr.responseText, xhr) + const uploadURL = body[opts.responseUrlFieldName] + +- const response = { ++ const uploadResp = { + status: ev.target.status, + body, + uploadURL + } + +- this.uppy.setFileState(file.id, { response }) +- +- this.uppy.emit('upload-success', file, body, uploadURL) ++ this.uppy.emit('upload-success', file, uploadResp) + + if (uploadURL) { + this.uppy.log(`Download ${file.name} from ${file.uploadURL}`)","the response data was added intentionally in #612, i think we could keep the `setFileState` stuff here as a special case, at least for now " +134,"@@ -134,7 +134,7 @@ func (s *stream) Read(p []byte) (int, error) { + } else { + select { + case <-s.readChan: +- case <-time.After(deadline.Sub(time.Now())): ++ case <-time.After(time.Until(deadline)): + } + } + s.mutex.Lock()",This isn't really easy to read. +135,"@@ -123,7 +123,7 @@ func (c *CStorVolumeReplicaController) cVREventHandler(operation common.QueueOpe + + err := volumereplica.DeleteVolume(fullVolName) + if err != nil { +- glog.Errorf(""Error in deleting volume %q: %s"", cVR.ObjectMeta.Name,err) ++ glog.Errorf(""Error in deleting volume %q: %s"", cVR.ObjectMeta.Name, err) + c.recorder.Event(cVR, corev1.EventTypeWarning, string(common.FailureDestroy), string(common.MessageResourceFailDestroy)) + return string(apis.CVRStatusDeletionFailed), err + }",This line changed due to go formatting. Format was not there earlier. +136,"@@ -28,13 +28,13 @@ type staticUpstream struct { + Path string + Interval time.Duration + } ++ Without string + } + + // NewStaticUpstreams parses the configuration input and sets up + // static upstreams for the proxy middleware. + func NewStaticUpstreams(c parse.Dispenser) ([]Upstream, error) { + var upstreams []Upstream +- + for c.Next() { + upstream := &staticUpstream{ + from: """",","The name ""Without"" in code is a little nebulous. Maybe something more descriptive like TrimPrefix or StripPrefix or WithoutPathPrefix or something like that. (Thoughts?)" +137,"@@ -254,6 +254,12 @@ public class MoveIT { + linkDataset.then().assertThat() + .statusCode(OK.getStatusCode()); + ++ // A dataset cannot be linked to the same dataverse again. ++ Response tryToLinkAgain = UtilIT.linkDataset(datasetPid, dataverse2Alias, superuserApiToken); ++ tryToLinkAgain.prettyPrint(); ++ tryToLinkAgain.then().assertThat() ++ .statusCode(FORBIDDEN.getStatusCode()); ++ + Response getLinksBefore = UtilIT.getDatasetLinks(datasetPid, superuserApiToken); + getLinksBefore.prettyPrint(); + getLinksBefore.then().assertThat()","is this test in the move tests? I see what you mean then - it works, but I wonder if we won't lose track that it's being tested here." +138,"@@ -368,5 +368,8 @@ type Instance struct { + EBSOptimized *bool `json:""ebsOptimized""` + + // The tags associated with the instance. +- Tags map[string]string `json:""tag""` ++ Tags map[string]string `json:""tags""` ++ ++ // The security groups associated with the instance. ++ SecurityGroups map[string]string `json:""securityGroups""` + }","I'm not sure if this wanted to be `json:""tags""` (which I'd set in my PR) or `json:""tag""` that someone elses PR had set. Given that the rest of the fields had their JSON field name set to the same as the struct field name, I opted for `tags`." +139,"@@ -47,6 +47,11 @@ module Ncr + message: ""must be three letters or numbers"" + }, allow_blank: true + ++ scope :for_fiscal_year, lambda { |year| ++ range = self.class.range_for_fiscal_year(year) ++ where(created_at: range[:start_time]...range[:end_time]) ++ } ++ + def self.all_system_approver_emails + [ + self.ba61_tier1_budget_mailbox,","since the logic here and in `Proposal` is exactly the same, do you think it makes sense for us to include it elsewhere? I am not opposed to duplicated code when it makes sense, but the reason I first identified this was that I was looking for code in NCR::WorkOrder that was not specific to Work Orders. Seems like fiscal year logic might be helpful for reporting for other clients. In that case, we'd want this scope on those client data classes as well. Might be wrong to include this in the FiscalYear mixin, but it does seem like it should be outside of Proposal and WorkOrder. Does that make sense?" +140,"@@ -42,6 +42,11 @@ class InfluxWriterSubscriber(object): + self.time = 0 + + ++ def on_connection_closed(self, connection, reply_code, reply_text): ++ self.log.info('RabbitMQ connection got closed!') ++ self.connection.add_timeout(5, self.connect_to_rabbitmq) ++ ++ + @staticmethod + def static_callback(ch, method, properties, body, obj): + return obj.callback(ch, method, properties, body)",there is no static method as a go between -- how does this work? +141,"@@ -0,0 +1,8 @@ ++# frozen_string_literal: true ++# encoding: utf-8 ++ ++class StringifiedSymbol ++ include Mongoid::Document ++ store_in collection: ""stringified_symbols"", client: :other ++ field :stringified_symbol, type: StringifiedSymbol ++end",Can you please change the name of this class to be something else? +142,"@@ -403,7 +403,7 @@ size_t h2o_strstr(const char *haysack, size_t haysack_len, const char *needle, s + } + + /* note: returns a zero-width match as well */ +-const char *h2o_next_token(h2o_iovec_t *iter, int separator, size_t *element_len, h2o_iovec_t *value) ++const char *h2o_next_token(h2o_iovec_t *iter, int separator, size_t *element_len, h2o_iovec_t *value, int coma_separator) + { + const char *cur = iter->base, *end = iter->base + iter->len, *token_start, *token_end; + ","I think we might prefer generalizing the interface rather than creating an exception. Current design of `h2o_next_token` assumes the input to be a comma-separated list, and allows the caller to specify a different separator when parsing a nested list. As I understand, what we are trying to attain in this PR is to have a way of parsing a flat list of semicolon-separated list. Assuming that is the case, I think it would be better to change the API of the function to accept two separators (i.e. inner and outer), where for our existing use-cases `outer` would be `,`." +143,"@@ -43,8 +43,8 @@ namespace Nethermind.Blockchain + { + private const long LowestInsertedBodyNumberDbEntryAddress = 0; + private const int CacheSize = 64; +- private readonly ICache _blockCache = new LruCacheWithRecycling(CacheSize, CacheSize, ""blocks""); +- private readonly ICache _headerCache = new LruCacheWithRecycling(CacheSize, CacheSize, ""headers""); ++ private readonly ICache _blockCache = new LruCache(CacheSize, CacheSize, ""blocks""); ++ private readonly ICache _headerCache = new LruCache(CacheSize, CacheSize, ""headers""); + + private const int BestKnownSearchLimit = 256_000_000; + ",why not recycling? I Lru cache now recycling? +144,"@@ -69,7 +69,7 @@ func (consumer *createConsumer) Consume(requestPtr interface{}) (response interf + issuerID := consumer.peerID + if request.ConsumerInfo != nil { + issuerID = request.ConsumerInfo.IssuerID +- if request.ConsumerInfo.PaymentVersion == PaymentVersionV2 { ++ if request.ConsumerInfo.PaymentVersion == PaymentVersionV3 { + indicateNewVersion = true + } + } else {",Why it is now called `PaymentVersionV3`? +145,"@@ -165,7 +165,7 @@ func (dc *DownstreamController) syncSecret() { + } + + nodes := dc.lc.SecretNodes(secret.Namespace, secret.Name) +- klog.Infof(""there are %d nodes need to sync secret, operation: %s"", len(nodes), e.Type) ++ klog.V(4).Infof(""there are %d nodes need to sync secret, operation: %s"", len(nodes), e.Type) + for _, n := range nodes { + msg := model.NewMessage("""") + msg.SetResourceVersion(secret.ResourceVersion)",changed for debug purpose? +146,"@@ -46,6 +46,13 @@ namespace OpenTelemetry + /// + public abstract override void OnEnd(T data); + ++ internal override void SetParentProvider(BaseProvider parentProvider) ++ { ++ base.SetParentProvider(parentProvider); ++ ++ this.exporter.ParentProvider = parentProvider; ++ } ++ + /// + protected override bool OnShutdown(int timeoutMilliseconds) + {",@cijothomas I needed a way to set the Exporter.ParentProvider when the Processor's gets set. Internal to SDK though. +147,"@@ -31,9 +31,13 @@ inline extractor::RoadClassification roadClass(const ConnectedRoad &road, + return graph.GetEdgeData(road.eid).flags.road_classification; + } + +-inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph) ++inline bool isRampClass(EdgeID eid, ++ const util::NodeBasedDynamicGraph &node_based_graph, ++ bool from_motorway = true) + { +- return node_based_graph.GetEdgeData(eid).flags.road_classification.IsRampClass(); ++ return node_based_graph.GetEdgeData(eid).flags.road_classification.IsRampClass() || ++ (from_motorway && ++ node_based_graph.GetEdgeData(eid).flags.road_classification.IsLinkClass()); + } + + } // namespace",Talking through this scenario with @srividyacb and she's wondering if there should also be a check of `(from_trunk && node_based_graph.GetEdgeData(eid).flags.road_classification.IsLinkClass())` as highways with trunk classifications can also have this scenario. +148,"@@ -13,7 +13,7 @@ module Beaker + :q_verify_packages => ENV['q_verify_packages'] || 'y', + :q_puppet_symlinks_install => 'y', + :q_puppetagent_certname => host, +- :q_puppetagent_server => master, ++ :q_puppetagent_server => master_certname, + + # Disable database, console, and master by default + # This will be overridden by other blocks being merged in.",where does `master_certname` come from? +149,"@@ -1,5 +1,7 @@ + from .resnet import ResNet, make_res_layer + from .resnext import ResNeXt + from .ssd_vgg import SSDVGG ++from .hrnet import HRNet + +-__all__ = ['ResNet', 'make_res_layer', 'ResNeXt', 'SSDVGG'] ++__all__ = ['ResNet', 'make_res_layer', 'ResNeXt', 'SSDVGG', ++ 'HRNet']",The line breaking is unnecessary. +150,"@@ -28,7 +28,7 @@ void DatasetLoader::SetHeader(const char* filename) { + // get column names + if (io_config_.has_header) { + std::string first_line = text_reader.first_line(); +- feature_names_ = Common::Split(first_line.c_str(), ""\t ,""); ++ feature_names_ = Common::Split(first_line.c_str(), ""\t,""); + } + + // load label idx first",why not enable split by space here ? +151,"@@ -1076,7 +1076,8 @@ fpga_result mmio_error(struct RASCommandLine *rasCmdLine) + return result; + } + +- if(value != FPGA_INTEGRATED_DEVICEID) { ++ if( (value != FPGA_INTEGRATED_DEVICEID) || ++ (value != FPGA_DISCRETE_DEVICEID) ) { + FPGA_ERR(""Failed to read Device id""); + return FPGA_NOT_SUPPORTED; + }",Shouldn't the operator be && ? +152,"@@ -161,6 +161,17 @@ module Beaker + FileUtils.rm_rf(@vagrant_path) + end + ++ #snapshotting depends on https://github.com/scalefactory/vagrant-multiprovider-snap ++ def take_snapshot(host,snapshot_name) ++ @logger.debug ""Creating snapshot of #{host}"" ++ vagrant_cmd(""snap take #{host} --name=#{snapshot_name}"") ++ end ++ ++ def restore_snapshot(host,snapshot_name) ++ @logger.debug ""Restoring snapshot of #{host}"" ++ vagrant_cmd(""snap rollback #{host} --name=#{snapshot_name}"") ++ end ++ + def vagrant_cmd(args) + Dir.chdir(@vagrant_path) do + exit_status = 1",My best guess is that you want to use host.name in these parts to get the name of the host ? +153,"@@ -270,13 +270,6 @@ func (n *Node) UnmarshalBinary(data []byte) error { + + n.entry = append([]byte{}, data[nodeHeaderSize:nodeHeaderSize+refBytesSize]...) + offset := nodeHeaderSize + refBytesSize // skip entry +- // Currently we don't persist the root nodeType when we marshal the manifest, as a result +- // the root nodeType information is lost on Unmarshal. This causes issues when we want to +- // perform a path 'Walk' on the root. If there is more than 1 fork, the root node type +- // is an edge, so we will deduce this information from index byte array +- if !bytes.Equal(data[offset:offset+32], make([]byte, 32)) { +- n.nodeType = nodeTypeEdge +- } + n.forks = make(map[byte]*fork) + bb := &bitsForBytes{} + bb.fromBytes(data[offset:])","IMO this edge case handling could remain here, just instead of overwriting the `n.nodeType`, the `makeEdgeType` method of `n` should be called, so `n.nodeType = nodeTypeEdge` -> `n.makeEdge()`" +154,"@@ -205,9 +205,10 @@ public class DownloadService extends Service { + Log.d(TAG, ""Service shutting down""); + isRunning = false; + ++ boolean showAutoDownloadReport = UserPreferences.showAutoDownloadReport(); + if (ClientConfig.downloadServiceCallbacks.shouldCreateReport() +- && UserPreferences.showDownloadReport()) { +- notificationManager.updateReport(reportQueue); ++ && (UserPreferences.showDownloadReport() || showAutoDownloadReport)) { ++ notificationManager.updateReport(reportQueue, showAutoDownloadReport); + reportQueue.clear(); + } + ","Just wondering... The two kinds of notifications are now quite different (Channel, text, maybe even icon). Would it make sense to extract the auto download notification to a new class instead of handling everything in the existing `notificationManager`? I have not checked if this will lead to a lot of code duplication, though." +155,"@@ -140,3 +140,11 @@ func (c *Call) RoutingDelegate() string { + } + return c.ic.req.RoutingDelegate + } ++ ++// Features returns the RequestFeatures for this request. ++func (c *Call) Features() transport.RequestFeatures { ++ if c == nil { ++ return transport.RequestFeatures{} ++ } ++ return c.ic.req.Features ++}",Do we need to put this on the Call? We only need the API communication between the Encoding and the Transports which is currently done through the Transport.Request. The Call is used by users right? +156,"@@ -1202,3 +1202,15 @@ L: + } + return filtered + } ++ ++func (a *WebAPI) GenerateAPIKey(ctx context.Context, req *webservice.GenerateAPIKeyRequest) (*webservice.GenerateAPIKeyResponse, error) { ++ return nil, status.Error(codes.Unimplemented, """") ++} ++ ++func (a *WebAPI) DisableAPIKey(ctx context.Context, req *webservice.DisableAPIKeyRequest) (*webservice.DisableAPIKeyResponse, error) { ++ return nil, status.Error(codes.Unimplemented, """") ++} ++ ++func (a *WebAPI) ListAPIKeys(ctx context.Context, req *webservice.ListAPIKeysRequest) (*webservice.ListAPIKeysResponse, error) { ++ return nil, status.Error(codes.Unimplemented, """") ++}",`ctx` is unused in GenerateAPIKey +157,"@@ -75,6 +75,7 @@ type ( + func NewBlockDAO(indexers []BlockIndexer, cfg config.DB) BlockDAO { + blkStore, err := filedao.NewFileDAO(cfg) + if err != nil { ++ log.L().Fatal(err.Error(), zap.Any(""cfg"", cfg)) + return nil + } + return createBlockDAO(blkStore, indexers, cfg)",Can you judge the type of error? +158,"@@ -204,7 +204,7 @@ class GridInterface(DictInterface): + if edges and not isedges: + data = cls._infer_interval_breaks(data) + elif not edges and isedges: +- data = np.convolve(data, [0.5, 0.5], 'valid') ++ data = data[:-1] + np.diff(data)/2. + return data + + ",Much simpler than a weird and confusing ``convolve`` call! +159,"@@ -739,8 +739,8 @@ describe('suspense', () => { + expect(scratch.innerHTML).to.eql( + `
Hello first 2
Hello second 2
` + ); +- expect(Suspender1.prototype.render).to.have.been.calledThrice; +- expect(Suspender2.prototype.render).to.have.been.calledThrice; ++ expect(Suspender1.prototype.render).to.have.been.calledTwice; ++ expect(Suspender2.prototype.render).to.have.been.calledTwice; + }); + }); + });","Huh, this seems weird to me... Surely the suspenders render was called again in order to get the new `
Hello second 2
` output... Imma take a peak at these tests to understand what's going on" +160,"@@ -80,6 +80,10 @@ class ApplicationController < ActionController::Base + def failed_destroy_error(obj, obj_name) + ""#{_('Could not delete the %{o}.') % {o: obj_name}} #{errors_to_s(obj)}"" + end ++ ++ def success_message(obj_name, action) ++ ""#{_('Successfully %{action} your %{object}.') % {object: obj_name, action: action}}"" ++ end + + private + # Override rails default render action to look for a branded version of a","Since this is just a helper function to create text, perhaps this could live in a helper? I noticed that we have a few other error/message creators in the application controller as well, but I think this type of function should be re-factored to be part of a helper." +161,"@@ -92,7 +92,7 @@ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / stateme + + # Template used to display messages. This is a python new-style format string + # used to format the message information. See doc for all details +-#msg-template= ++msg-template=[{msg_id}] {path}:{line:3d}:{column}: {msg} + + + [SPELLING]","Will this mess up parsing the messages by other editors? (vscode, vim ...)" +162,"@@ -1,4 +1,3 @@ +-# Set up gems listed in the Gemfile. +-ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) ++ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +-require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) ++require 'bundler/setup' # Set up gems listed in the Gemfile.",Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. +163,"@@ -28,8 +28,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter + _filteredStream = filteredStream; + _socketInputStream = new SocketInputStream(SocketInput); + +- _filteredStream.CopyToAsync(_socketInputStream).ContinueWith((task, state) => ++ var block = memory.Lease(); ++ // Use pooled block for copy ++ _filteredStream.CopyToAsync(_socketInputStream, block).ContinueWith((task, state) => + { ++ var returnedBlock = task.Result; ++ returnedBlock.Pool?.Return(returnedBlock); ++ + ((FilteredStreamAdapter)state).OnStreamClose(task); + }, this); + }",Why can the pool be null? +164,"@@ -74,6 +74,15 @@ class ToggleButton(ia2Web.Ia2Web): + return states + + ++class PresentationalList(ia2Web.Ia2Web): ++ """""" Ensures that lists like UL, DL and OL always have the readonly state."""""" ++ ++ def _get_states(self): ++ states = super().states ++ states.add(controlTypes.STATE_READONLY) ++ return states ++ ++ + def findExtraOverlayClasses(obj, clsList): + """"""Determine the most appropriate class(es) for Chromium objects. + This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses} except that it never calls any other findOverlayClasses method.","It might be good to have a note here: > work-around for issue #7562 allowing us to differentiate presentational lists from interactive lists (such as of size greater 1 and ARIA list boxes). In firefox, this is possible by the presence of a read-only state, even in content editable." +165,"@@ -66,16 +66,16 @@ import java.util.Set; + * the current node) may be queried. + * + */ +-class DigraphNode implements Cloneable, Serializable { ++class DigraphNode implements Cloneable, Serializable { + + /** The data associated with this node. */ +- protected Object data; ++ protected E data; + + /** + * A Set of neighboring nodes pointed to by this + * node. + */ +- protected Set outNodes = new HashSet(); ++ protected Set> outNodes = new HashSet<>(); + + /** The in-degree of the node. */ + protected int inDegree = 0;",This set of changes is the one part of this that I'm not completely sure is valid. Can someone look over this to make sure I got the E's right? +166,"@@ -282,8 +282,12 @@ void nano::bootstrap_attempt_legacy::request_push (nano::unique_lock + void nano::bootstrap_attempt_legacy::add_frontier (nano::pull_info const & pull_a) + { + nano::pull_info pull (pull_a); +- nano::lock_guard lock (mutex); +- frontier_pulls.push_back (pull); ++ // Prevent incorrent or malicious pulls with frontier 0 insertion ++ if (!pull.head.is_zero ()) ++ { ++ nano::lock_guard lock (mutex); ++ frontier_pulls.push_back (pull); ++ } + } + + void nano::bootstrap_attempt_legacy::add_bulk_push_target (nano::block_hash const & head, nano::block_hash const & end)",There doesn't seem to be a reason to copy this here. +167,"@@ -1774,6 +1774,7 @@ std::string h2o_raw_tracer::bpf_text() { + + #include + #include ++#include ""include/h2o/ebpf.h"" + + #define STR_LEN 64 + ","We've avoided including h2o headers in BPF programs because it's a runtime dependency. However, IIRC, this is because h2olog was maintained in the separate repository so that h2olog did not know where h2o was installed. Now h2olog can use `H2O_ROOT`, we should add it to BCC's `cflags` in order to include h2o headers in BPF programs." +168,"@@ -170,6 +170,10 @@ type ThanosRulerSpec struct { + // Note: Currently only the CAFile, CertFile, and KeyFile fields are supported. + // Maps to the '--grpc-server-tls-*' CLI args. + GRPCServerTLSConfig *TLSConfig `json:""grpcServerTlsConfig,omitempty""` ++ // The external Query URL the Thanos Ruler will set in the 'Source' field ++ // of all alerts. ++ // Maps to the '--alert.query-url' CLI arg. ++ AlertQueryURL string `json:""alertQueryUrl,omitempty""` + } + + // ThanosRulerStatus is the most recent observed status of the ThanosRuler. Read-only. Not",I think the docstring here should include the CLI arg `--alert.query-url` just to make it clear to users which setting this uses. +169,"@@ -224,9 +224,7 @@ func (m *ipipManager) CompleteDeferredWork() error { + for _, ip := range m.activeHostnameToIP { + members = append(members, ip) + } +- for _, ip := range m.externalNodeCIDRs { +- members = append(members, ip) +- } ++ members = append(members, m.externalNodeCIDRs...) + m.ipsetsDataplane.AddOrReplaceIPSet(m.ipSetMetadata, members) + m.ipSetInSync = true + }",Same change just above? +170,"@@ -511,4 +511,14 @@ describe('services_SearchEngine', function() { + expect((await engine.search('""- [ ]""', { searchType: SearchEngine.SEARCH_TYPE_BASIC })).length).toBe(1); + expect((await engine.search('""[ ]""', { searchType: SearchEngine.SEARCH_TYPE_BASIC })).length).toBe(2); + })); ++ ++ it('should not mistake cyrillic ""l"" for latin ""n""', asyncTest(async () => { ++ const n1 = await Note.save({ title: 'latin n', body: 'n' }); ++ const n2 = await Note.save({ title: 'cyrillic l', body: 'л' }); ++ ++ await engine.syncTables(); ++ ++ expect((await engine.search('n')).length).toBe(1); ++ expect((await engine.search('л')).length).toBe(1); ++ })); + });","Could you check the result content rather than just the number of search results please? For example with this test if the search engine suddenly starts returning ""latin n"" for both queries, we won't know about it." +171,"@@ -47,9 +47,10 @@ const ( + + otherDomainID = ""spiffe://otherdomain.test"" + +- serverID = ""spiffe://example.org/spire/server"" +- agentID = ""spiffe://example.org/spire/agent/test/id"" +- workloadID = ""spiffe://example.org/workload"" ++ serverID = ""spiffe://example.org/spire/server"" ++ agentID = ""spiffe://example.org/spire/agent/test/id"" ++ agentlessID = ""spiffe://example.org/test/id"" ++ workloadID = ""spiffe://example.org/workload"" + + // used to cancel stream operations on test failure instead of blocking the + // full go test timeout period (i.e. 10 minutes)",nit: I think that `workloadID` should suffice for this test... that's what we'd be issuing anyways +172,"@@ -1,4 +1,4 @@ +-require 'spec_helper' ++require 'rails_helper' + + feature 'Admin manages mentors' do + scenario 'creating a new mentor' do",Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. +173,"@@ -204,11 +204,7 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { + if (className != null) { + populateClassName(node, className); + } +- } catch (ClassNotFoundException e) { +- if (LOG.isLoggable(Level.FINE)) { +- LOG.log(Level.FINE, ""Could not find class "" + className + "", due to: "" + e); +- } +- } catch (NoClassDefFoundError e) { ++ } catch (ClassNotFoundException | NoClassDefFoundError e) { + if (LOG.isLoggable(Level.FINE)) { + LOG.log(Level.FINE, ""Could not find class "" + className + "", due to: "" + e); + }",We should have a rule to detect identical catch branches +174,"@@ -28,10 +28,6 @@ namespace Microsoft.DotNet.Build.Tasks.Feed + + public bool PublishFlatContainer { get; set; } + +- public int RetryAttempts { get; set; } = 5; +- +- public int RetryDelayInSeconds { get; set; } = 30; +- + public int MaxClients { get; set; } = 8; + + public bool SkipCreateContainer { get; set; } = false;",remove these from the targets file. +175,"@@ -11,14 +11,13 @@ import ( + ""time"" + + ""github.com/ethersphere/bee/pkg/addressbook"" ++ ""github.com/ethersphere/bee/pkg/bzz"" + ""github.com/ethersphere/bee/pkg/hive/pb"" + ""github.com/ethersphere/bee/pkg/logging"" + ""github.com/ethersphere/bee/pkg/p2p"" + ""github.com/ethersphere/bee/pkg/p2p/protobuf"" + ""github.com/ethersphere/bee/pkg/storage"" + ""github.com/ethersphere/bee/pkg/swarm"" +- +- ma ""github.com/multiformats/go-multiaddr"" + ) + + const (","now that we have the signature in the hive messages, it might be that this must be drastically reduced, since there are limits on the protobuf reader/writers i believe" +176,"@@ -35,11 +35,12 @@ NAMESPACE_PACKAGES = [ + REQUIRED_PACKAGES = [ + # Installation related. + 'anytree==2.4.3', +- 'google-api-python-client==1.7.7', +- 'google-auth==1.6.2', ++ 'google-api-python-client==1.7.10', ++ 'google-auth==1.6.3', + 'google-auth-httplib2==0.0.3', + 'Jinja2==2.10.1', + 'jmespath==0.9.3', ++ 'mailjet-rest==1.3.3', + 'netaddr==0.7.19', + 'pyyaml==4.2b4', + 'python-graph-core==1.8.2',","I recommend that we move this to be optional, as other users might not need it. Can you look at `OPTIONAL_PACKAGES` section, around line 68?" +177,"@@ -8,10 +8,7 @@ package javaslang.control; + import javaslang.Serializables; + import org.junit.Test; + +-import java.util.Iterator; +-import java.util.NoSuchElementException; +-import java.util.Objects; +-import java.util.Optional; ++import java.util.*; + + import static org.assertj.core.api.Assertions.assertThat; + ",I usually set idea to never use wildcard import such as `import java.util.*;` Now i use setting from javaslang standard. +178,"@@ -29,7 +29,9 @@ module Beaker + v_file << "" v.vm.box = '#{host['box']}'\n"" + v_file << "" v.vm.box_url = '#{host['box_url']}'\n"" unless host['box_url'].nil? + v_file << "" v.vm.base_mac = '#{randmac}'\n"" +- v_file << "" v.vm.network :private_network, ip: \""#{host['ip'].to_s}\"", :netmask => \""#{host['netmask'] ||= ""255.255.0.0""}\""\n"" ++ host['ips'].each do |ip| ++ v_file << "" v.vm.network :private_network, ip: \""#{ip.to_s}\"", :netmask => \""#{host['netmask'] ||= ""255.255.0.0""}\""\n"" ++ end + + if host['disk_path'] + v_file << "" v.vm.provider :virtualbox do |vb|\n""",Where is host['ips'] coming from? +179,"@@ -3,14 +3,7 @@ + + package userns + +-import ( +- ""strings"" +- +- ""github.com/opencontainers/runc/libcontainer/user"" +-) +- +-func FuzzUIDMap(data []byte) int { +- uidmap, _ := user.ParseIDMap(strings.NewReader(string(data))) +- _ = uidMapInUserNS(uidmap) ++func FuzzUIDMap(uidmap []byte) int { ++ _ = uidMapInUserNS(string(uidmap)) + return 1 + }",oh! missed a `:` here; let me fix that; also can get rid of the intermediate variable +180,"@@ -1,6 +1,8 @@ + describe ""Display status text"" do + let(:proposal) { FactoryGirl.create(:proposal, :with_parallel_approvers) } + before do ++ proposal.approvers.first.update(first_name: ""Uniquely"", last_name: ""Named"") ++ proposal.approvers.second.update(first_name: ""Onlyof"", last_name: ""Itskind"") + login_as(proposal.requester) + end + ",Is this necessary? +181,"@@ -1,8 +1,16 @@ +-import React from 'react'; ++import React, {Component} from 'react'; + import 'element-theme-default'; + import {i18n} from 'element-react'; + import locale from 'element-react/src/locale/lang/en'; + ++import storage from './utils/storage'; ++import logo from './utils/logo'; ++import {makeLogin, isTokenExpire} from './utils/login'; ++ ++import Header from './components/Header'; ++import Footer from './components/Footer'; ++import LoginModal from './components/Login'; ++ + i18n.use(locale); + + import Route from './router';",I'd create a different method for each render section. +182,"@@ -23,6 +23,8 @@ public class EstimateGasOperationTracer implements OperationTracer { + + private Gas sStoreStipendNeeded = Gas.ZERO; + ++ private boolean isReverted = false; ++ + @Override + public void traceExecution( + final MessageFrame frame, final OperationTracer.ExecuteOperation executeOperation) {",Instead of storing the revert flag in the tracer is it possible to use org.hyperledger.besu.ethereum.mainnet.TransactionProcessor.Result#getRevertReason? (via org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult#getResult)? If a TX reverts without a reason do we get an empty revert reason or a revert reason with zero bytes? +183,"@@ -71,7 +71,7 @@ public class TestSparkOrcReader extends AvroDataTest { + + try (CloseableIterable reader = ORC.read(Files.localInput(testFile)) + .project(schema) +- .createReaderFunc(SparkOrcReader::new) ++ .createReaderFunc(readOrcSchema -> new SparkOrcReader(schema, readOrcSchema)) + .build()) { + final Iterator actualRows = reader.iterator(); + final Iterator expectedRows = expected.iterator();",I think this should test with and without container reuse if that is implemented in this PR. Probably just make this test parameterized. +184,"@@ -100,6 +100,10 @@ abstract class BaseFile + found = true; + fromProjectionPos[i] = j; + } ++ if (fields.get(i).fieldId() == ManifestFile.SPEC_ID.fieldId()) { ++ found = true; ++ fromProjectionPos[i] = 14; ++ } + } + + if (!found) {",These modifications allow BaseFile to translate into a SparkRow with the specID as a column +185,"@@ -519,7 +519,7 @@ function resolveReadPreference(parent, options) { + throw new Error('No readPreference was provided or inherited.'); + } + +- return readPreference; ++ return typeof readPreference === 'string' ? new ReadPreference(readPreference) : readPreference; + } + + /**",is this something we've been missing this whole time? +186,"@@ -25,6 +25,7 @@ import ( + const ( + defaultWaitApprovalTimeout = Duration(6 * time.Hour) + defaultAnalysisQueryTimeout = Duration(30 * time.Second) ++ allEvents = ""*"" + ) + + type GenericDeploymentSpec struct {",nit: this is a package-wide constant so better to narrow the scope like `allEventsSign`. +187,"@@ -111,6 +111,15 @@ def generate_thrift_files(thrift_files_dir, env, silent=True): + LOG.error('Failed to generate viewer server files') + return ret + ++ auth_thrift = os.path.join(thrift_files_dir, 'authentication.thrift') ++ auth_thrift = 'authentication.thrift' ++ auth_cmd = ['thrift', '-r', '-I', '.', ++ '--gen', 'py', auth_thrift] ++ ret = run_cmd(auth_cmd, thrift_files_dir, env, silent=silent) ++ if ret: ++ LOG.error('Failed to generate authentication interface files') ++ return ret ++ + + # ------------------------------------------------------------------- + def generate_documentation(doc_root, env, silent=True):",There seems to be some repetition. Does a local function make this code shorter overall? +188,"@@ -298,6 +298,7 @@ function diffElementNodes( + } + + if (dom == null) { ++ isHydrating = false; + if (newVNode.type === null) { + return document.createTextNode(newProps); + }",Might be cheaper to reuse the `null` assignment of line 313 and set `isHydrating` to null instead WDYT? +189,"@@ -22,7 +22,6 @@ import java.util.List; + + @AutoValue + public abstract class TestCaseView { +- + public abstract String clientMethodName(); + + public abstract InitCodeView initCode();",Revert this blank line +190,"@@ -50,8 +50,8 @@ public class MoveReplicaHDFSTest extends MoveReplicaTest { + HdfsTestUtil.teardownClass(dfsCluster); + } finally { + dfsCluster = null; +- System.setProperty(""solr.hdfs.blockcache.blocksperbank"", ""512""); +- System.setProperty(""tests.hdfs.numdatanodes"", ""1""); ++ System.clearProperty(""solr.hdfs.blockcache.blocksperbank""); ++ System.clearProperty(""tests.hdfs.numdatanodes""); + } + } + ",This was introduced recently for the Hadoop 3 upgrade. Copy/paste error but definitely causing some of the new test failures. +191,"@@ -2,6 +2,7 @@ class ProposalsController < ApplicationController + include TokenAuth + + skip_before_action :authenticate_user!, only: [:approve] ++ before_action :check_disabled_client + # TODO use Policy for all actions + before_action ->{authorize proposal}, only: [:show, :cancel, :cancel_form, :history] + before_action :needs_token_on_get, only: :approve",I think we should only need to do this for `:approve` since we are using `authenticate_user!` for all other actions and that checks for disabled client +192,"@@ -56,9 +56,10 @@ class DefaultBucketViewTest(BaseWebTest, unittest.TestCase): + self.app.get(self.collection_url, headers=self.headers) + + def test_querystring_parameters_are_taken_into_account(self): +- self.app.get(self.collection_url + '/records?_since=invalid', +- headers=self.headers, +- status=400) ++ resp = self.app.get(self.collection_url + '/records?_since=invalid', ++ headers=self.headers, ++ status=400) ++ self.assertIn('Content-Length', resp.headers) + + def test_option_is_possible_without_authentication_for_default(self): + headers = 'authorization,content-type'",I wonder if we should create new tests for header checks; here for instance we're mixing querystring and headers. Thoughts? +193,"@@ -42,7 +42,7 @@ module Bolt + path = File.join(libexec, 'custom_facts.rb') + file = { 'name' => 'custom_facts.rb', 'path' => path } + metadata = { 'supports_noop' => true, 'input_method' => 'stdin' } +- Bolt::Task.new(name: 'custom_facts', files: [file], metadata: metadata) ++ Bolt::Task.new(name: 'apply_helpers::custom_facts', files: [file], metadata: metadata) + end + end + ","We should be able to add sensitive by hard-coding the parameters, same as you put into the metadata in apply_helpers." +194,"@@ -0,0 +1,11 @@ ++all(FLERR, str); ++ snprintf(str,128,""unknown *KEYWORD: %s"", arg[ioffset]); ++ error->all(FLERR, str); + } + + }",this one bothers me. There are many places where this one is written to for an error message and just a single callsite is changed. +204,"@@ -706,6 +706,7 @@ func TestKBFSOpsGetBaseDirChildrenCacheSuccess(t *testing.T) { + ops := getOps(config, id) + n := nodeFromPath(t, ops, p) + ++ config.mockMdserv.EXPECT().FastForwardBackoff().AnyTimes() + children, err := config.KBFSOps().GetDirChildren(ctx, n) + if err != nil { + t.Errorf(""Got error on getdir: %+v"", err)","You can put this in `kbfsOpsInit()` in you want, so we don't have to call it in every test." +205,"@@ -528,8 +528,10 @@ drx_insert_counter_update(void *drcontext, instrlist_t *ilist, instr_t *where, + } + } + #elif defined(AARCHXX) ++# ifdef ARM_32 + /* FIXME i#1551: implement 64-bit counter support */ +- ASSERT(!is_64, ""DRX_COUNTER_64BIT is not implemented""); ++ ASSERT(!is_64, ""DRX_COUNTER_64BIT is not implemented for ARM_32""); ++# endif /* ARM_32 */ + + if (use_drreg) { + if (drreg_reserve_register(drcontext, ilist, where, NULL, ®1) !=","`ARM_32` is what clients define as an input to DR, and is not always defined internally: we use just `ARM` to mean AArch32." +206,"@@ -38,8 +38,11 @@ import javax.annotation.Nullable; + /** A field declaration wrapper around a Discovery Schema. */ + public class DiscoveryField implements FieldModel, TypeModel { + private final List properties; ++ // Dereferenced schema for use rendering type names and determining properties, type, and format. + private final Schema schema; +- private final Schema originalSchema; // Not dereferenced schema. ++ ++ // Not dereferenced schema; used in rendering this FieldModel's parameter name. ++ private final Schema originalSchema; + private final DiscoApiModel apiModel; + + /* Create a FieldModel object from a non-null Schema object, and internally dereference the input schema. */",s/for use/to use for/ +207,"@@ -60,7 +60,7 @@ class UserCreatedEventProjector + 'language' => $event->getLanguage()->getCode(), + 'password' => $event->getPassword()->getValue(), + 'is_active' => $event->isActive(), +- 'avatar_id' => $event->getAvatarId() ? $event->getAvatarId()->getValue() : null, ++ 'avatar_filename' => $event->getAvatarFilename() ? $event->getAvatarFilename()->getValue() : null, + ], + [ + 'is_active' => \PDO::PARAM_BOOL,",` $event->getAvatarFilename()` this function return `string` or `null`. In this place ` $event->getAvatarFilename()->getValue()` return `Fatal error ` +208,"@@ -34,7 +34,7 @@ import ( + + var ( + // ErrPersistenceLimitExceeded is the error indicating QPS limit reached. +- ErrPersistenceLimitExceeded = serviceerror.NewResourceExhausted(""Persistence Max QPS Reached."") ++ ErrPersistenceLimitExceeded = serviceerror.NewUnavailable(""Persistence Max QPS Reached."") + ) + + type (",why not creating a new error type for server's own resource limit exceed error and do conversion within rpc interceptor? +209,"@@ -27,13 +27,10 @@ namespace OpenTelemetry.Instrumentation.AspNet + public class AspNetInstrumentationOptions + { + /// +- /// Gets or sets for context propagation. Default value: with & . ++ /// Gets or sets for context propagation. ++ /// By default, will be used. + /// +- public TextMapPropagator Propagator { get; set; } = new CompositeTextMapPropagator(new TextMapPropagator[] +- { +- new TraceContextPropagator(), +- new BaggagePropagator(), +- }); ++ public TextMapPropagator Propagator { get; set; } = Propagators.DefaultTextMapPropagator; + + /// + /// Gets or sets a Filter function to filter instrumentation for requests on a per request basis.","Could be a timing thing here. When options are created they'll copy the ref for the current default propagator. If user sets through SDK the global propagator after that, it won't be reflected. Could leave it null here and then when it is used in instrumentation do `options.Propagator ?? Propagators.DefaultTextMapPropagator`. It would be a slight perf hit but it makes it hot-swappable." +210,"@@ -158,7 +158,6 @@ public class TransactionSimulator { + callParams.getFrom() != null ? callParams.getFrom() : DEFAULT_FROM; + + BlockHeader blockHeaderToProcess = header; +- + if (transactionValidationParams.isAllowExceedingBalance()) { + updater.getOrCreate(senderAddress).getMutable().setBalance(Wei.of(UInt256.MAX_VALUE)); + if (header.getBaseFee().isPresent()) {",Unrelated file. Please remove from PR. +211,"@@ -2663,6 +2663,7 @@ static work_queue_msg_code_t process_http_request( struct work_queue *q, struct + } else { + // Other requests get raw JSON data. + send_worker_msg(q,w,""Content-type: text/plain\n\n""); ++ send_worker_msg(q,w,""Access-Control-Allow-Origin: *\n\n""); + process_queue_status(q, w, &path[1], stoptime ); + } + ",Careful: you only want two newlines after the final header message. (That indicates the end of headers and the start of data.) +212,"@@ -9,6 +9,9 @@ def request(flow): + flow.request.headers.pop('If-Modified-Since', None) + flow.request.headers.pop('Cache-Control', None) + ++ # do not force https redirection ++ flow.request.headers.pop('Upgrade-Insecure-Requests', None) ++ + # proxy connections to SSL-enabled hosts + if flow.request.pretty_host in secure_hosts: + flow.request.scheme = 'https'","This will not work on Python 3 (to which we are transitioning) because `.content` is bytes, not a str. Can you make the pattern a bytes object as well (like so: `b""pattern""`)?" +213,"@@ -85,7 +85,7 @@ const ariaRoles = { + }, + combobox: { + type: 'composite', +- requiredOwned: ['textbox', 'listbox', 'tree', 'grid', 'dialog'], ++ requiredOwned: ['listbox', 'tree', 'grid', 'dialog', 'textbox'], + requiredAttrs: ['aria-expanded'], + // Note: because aria-controls is not well supported we will not + // make it a required attribute even though it is required in the","This was to allow the tests to pass when the order of the required was different. Silly, but we don't have an easy way to check for ""equal but order doesn't matter"" in chai." +214,"@@ -16546,6 +16546,18 @@ RelInternalSP::costMethod() const + } // RelInternalSP::costMethod() + // + ++CostMethod * ++HbaseDelete::costMethod() const ++{ ++ if (CmpCommon::getDefault(HBASE_DELETE_COSTING) == DF_OFF) ++ return RelExpr::costMethod(); // returns cost 1 cost object ++ ++ static THREAD_P CostMethodHbaseDelete *m = NULL; ++ if (m == NULL) ++ m = new (GetCliGlobals()->exCollHeap()) CostMethodHbaseDelete(); ++ return m; ++} // HbaseDelete::costMethod() ++ + PhysicalProperty* + HbaseDelete::synthPhysicalProperty(const Context* myContext, + const Lng32 planNumber,","maybe say ""returns the default cost method that returns an object of cost 1""." +215,"@@ -293,6 +293,19 @@ func (r *DefaultRuleRenderer) endpointIptablesChain( + }, + }) + ++ rules = append(rules, Rule{ ++ Match: Match().ProtocolNum(ProtoUDP). ++ DestPorts(uint16(r.Config.VXLANPort)). ++ VXLANVNI(uint32(r.Config.VXLANVNI)), ++ Action: DropAction{}, ++ Comment: ""Drop VXLAN encapped packets originating in pods"", ++ }) ++ rules = append(rules, Rule{ ++ Match: Match().ProtocolNum(ProtoIPIP), ++ Action: DropAction{}, ++ Comment: ""Drop IPinIP encapped packets originating in pods"", ++ }) ++ + if len(policyNames) > 0 { + // Clear the ""pass"" mark. If a policy sets that mark, we'll skip the rest of the policies and + // continue processing the profiles, if there are any.","I believe these rules will be enforced both (1) on egress from a local workload, and (2) on ingress **to** a local workload. Right? I understand that we definitely want (1), but do we really want to enforce (2) as well?" +216,"@@ -125,7 +125,9 @@ public class SalesforceNetworkPlugin extends ForcePlugin { + try { + // Not a 2xx status + if (!response.isSuccess()) { +- callbackContext.error(response.asString()); ++ JSONObject errorObj = new JSONObject(); ++ errorObj.putOpt(""response"", response.fullResponseAsJSONObject()); ++ callbackContext.error(errorObj.toString()); + } + // Binary response + else if (returnBinary) {","Use `response.asJsonObject()` instead. Also, use `put()` instead of `putOpt()`, `null` as a value is fine." +217,"@@ -113,7 +113,7 @@ describe('PasswordEditor', () => { + const editorHolder = $('.handsontableInputHolder'); + const editor = editorHolder.find('.handsontableInput'); + +- expect(parseInt(editorHolder.css('z-index'), 10)).toBeGreaterThan(0); ++ expect(editorHolder.is(':visible')).toBe(true); + + editor.val('Edgar'); + ",Are you sure? We've changed it during an introduction of the IME support. +218,"@@ -46,7 +46,7 @@ class QueryBuilder + $queryBuilder->leftJoin('entity.'.$sortFieldParts[0], $sortFieldParts[0]); + } + +- if (!empty($dqlFilter)) { ++ if (null !== $dqlFilter) { + $queryBuilder->andWhere($dqlFilter); + } + ","I think here we want the use of `empty()` to take care of empty strings. If you put `dql_filter: ''` in your YAML config ... this will add `->andWhere('')` and it will fail, right?" +219,"@@ -170,14 +170,12 @@ func (p *Agent) Start(ctx context.Context) error { + p2pMsgLatency.WithLabelValues(""broadcast"", strconv.Itoa(int(broadcast.MsgType)), status).Observe(float64(latency)) + }() + if err = proto.Unmarshal(data, &broadcast); err != nil { +- err = errors.Wrap(err, ""error when marshaling broadcast message"") +- return ++ return errors.Wrap(err, ""error when marshaling broadcast message"") + } + // Skip the broadcast message if it's from the node itself + rawmsg, ok := p2p.GetBroadcastMsg(ctx) + if !ok { +- err = errors.New(""error when asserting broadcast msg context"") +- return ++ return errors.New(""error when asserting broadcast msg context"") + } + peerID = rawmsg.GetFrom().Pretty() + if p.host.HostIdentity() == peerID {","this is golang's named return, err is defined, `return` is equivalent to `return err` the current code has no problem" +220,"@@ -202,7 +202,7 @@ ostree_gpg_verify_result_get_all (OstreeGpgVerifyResult *result, + * ostree_gpg_verify_result_describe: + * @result: an #OstreeGpgVerifyResult + * @signature_index: which signature to describe +- * @output_buffer: a #GString to hold the description ++ * @output_buffer: (out): a #GString to hold the description + * @line_prefix: (allow-none): optional line prefix string + * @flags: flags to adjust the description format + *","I don't think this is right; in Rust terms it's like a `&mut String`, in Java `StringBuilder` - it's not a return value from the function which is what `(out)` is for." +221,"@@ -7,9 +7,9 @@ from ..registry import LOSSES + + def _expand_binary_labels(labels, label_weights, label_channels): + bin_labels = labels.new_full((labels.size(0), label_channels), 0) +- inds = torch.nonzero(labels >= 1).squeeze() ++ inds = torch.nonzero((labels >= 0) & (labels < label_channels)).squeeze() + if inds.numel() > 0: +- bin_labels[inds, labels[inds] - 1] = 1 ++ bin_labels[inds, labels[inds]] = 1 + bin_label_weights = label_weights.view(-1, 1).expand( + label_weights.size(0), label_channels) + return bin_labels, bin_label_weights","If the label is not binary, should we rename this function?" +222,"@@ -421,10 +421,12 @@ class JMeterExecutor(ScenarioExecutor, WidgetProvider, FileLister): + :param file_list: + :return: etree + """""" ++ cur_path = r""${__BeanShell(import org.apache.jmeter.services.FileServer; FileServer.getFileServer()"" \ ++ r"".getBaseDir();)}${__BeanShell(File.separator,)}"" + for file_path in file_list: + file_path_elements = jmx.xpath('//stringProp[text()=""%s""]' % file_path) + for file_path_element in file_path_elements: +- file_path_element.text = os.path.basename(file_path) ++ file_path_element.text = cur_path + os.path.basename(file_path) + + def __get_resource_files_from_jmx(self, jmx): + """"""",This is very-very bad idea because of its performance impact +223,"@@ -6,6 +6,7 @@ import ( + ""database/sql"" + ""encoding/json"" + ""fmt"" ++ ""github.com/sonm-io/core/proto"" + ""math/big"" + ""net"" + ""sync""",WHY U NOT SORT IMPORTS? +224,"@@ -0,0 +1,11 @@ ++module SignInRequestHelpers ++ def sign_in_as(user) ++ post( ++ ""/session"", ++ session: { ++ email: user.email, ++ password: user.password, ++ }, ++ ) ++ end ++end",Put a comma after the last item of a multiline hash. +225,"@@ -12,7 +12,7 @@ __version__ = param.Version(release=(1,7,0), fpath=__file__, + commit=""$Format:%h$"", reponame='holoviews') + + from .core import archive # noqa (API import) +-from .core.dimension import OrderedDict, Dimension # noqa (API import) ++from .core.dimension import OrderedDict, Dimension, Dimensioned # noqa (API import) + from .core.boundingregion import BoundingBox # noqa (API import) + from .core.options import (Options, Store, Cycle, # noqa (API import) + Palette, StoreOptions)",How come we need ``Dimensioned`` in the top-level namespace? +226,"@@ -75,9 +75,9 @@ import net.runelite.client.util.Text; + import net.runelite.client.util.WildcardMatcher; + + @PluginDescriptor( +- name = ""NPC Indicators"", +- description = ""Highlight NPCs on-screen and/or on the minimap"", +- tags = {""highlight"", ""minimap"", ""npcs"", ""overlay"", ""respawn"", ""tags""} ++ name = ""NPC Indicators"", ++ description = ""Highlight NPCs on-screen and/or on the minimap"", ++ tags = {""highlight"", ""minimap"", ""npcs"", ""overlay"", ""respawn"", ""tags""} + ) + @Slf4j + @Singleton",excess whitespace through plugin. +227,"@@ -138,7 +138,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI + NodeID current_edge_source_coordinate_id = node_u; + + // traverse arrays from start and end respectively +- for (const auto i : util::irange(0UL, geometry_size)) ++ for (const auto i : util::irange(std::size_t{ 0 }, geometry_size)) + { + BOOST_ASSERT(current_edge_source_coordinate_id == + m_compressed_edge_container.GetBucketReference(",What is the problem here? I feel we used this in a lot of places. +228,"@@ -109,8 +109,7 @@ class RPN(BaseDetector): + for proposals, meta in zip(proposal_list, img_metas): + proposals[:, :4] /= proposals.new_tensor(meta['scale_factor']) + +- # TODO: remove this restriction +- return proposal_list[0].cpu().numpy() ++ return [proposal.cpu().numpy() for proposal in proposal_list] + + def aug_test(self, imgs, img_metas, rescale=False): + """"""Test function with test time augmentation.",Update the docstring. +229,"@@ -7,10 +7,11 @@ + package api + + import ( +- ""errors"" + ""testing"" + ""time"" + ++ ""github.com/pkg/errors"" ++ + ""github.com/golang/mock/gomock"" + ""github.com/stretchr/testify/require"" + ","delete the empty line ""github.com/pkg/errors"" should be grouped with other third party packages same for the rest" +230,"@@ -155,7 +155,7 @@ public class RemoteWebDriver implements WebDriver, JavascriptExecutor, + } + + private void init(Capabilities capabilities) { +- capabilities = capabilities == null ? new ImmutableCapabilities() : capabilities; ++ this.capabilities = capabilities == null ? new ImmutableCapabilities() : capabilities; + + logger.addHandler(LoggingHandler.getInstance()); + ",Assigning capabilities to the field here is not the best idea. Semantically this field contains the capabilities returned by the browser after session start. So here we sould better amend capabilities and return them from `init` method to pass later to `startSession` method (that will assign the capabilities returned by the browser to the field). +231,"@@ -110,8 +110,6 @@ module RSpec::Core + end + end + +- alias_method :abort, :finish +- + def stop + @duration = (RSpec::Core::Time.now - @start).to_f if @start + notify :stop","Is this a breaking change, or is the API private?" +232,"@@ -0,0 +1,4 @@ ++import pandas as pd ++ ++test_data = pd.read_json(""./dumps/courseData.json""); ++test_data = {k: val.groupby('pk')['fields'].apply(list).apply(lambda x: x[0]).to_dict() for k, val in test_data.groupby(""model"")};",I don't think we need this dependency in this project right now +233,"@@ -30,8 +30,9 @@ const ( + // FanoutName is the name used for the fanout container. + FanoutName = ""fanout"" + // RetryName is the name used for the retry container. +- RetryName = ""retry"" +- BrokerCellLabelKey = ""brokerCell"" ++ RetryName = ""retry"" ++ BrokerCellLabelKey = ""brokerCell"" ++ BrokerSystemNamespace = ""cloud-run-events"" + ) + + var (",I don't think this is necessary since `CommonLabels` is a public func and every component name is also public constant. +234,"@@ -155,14 +155,15 @@ module Bolt + ""`task.py`) and the extension is case sensitive. When a target's name is `localhost`, ""\ + ""Ruby tasks run with the Bolt Ruby interpreter by default."", + additionalProperties: { +- type: String, ++ type: [String, Array], + _plugin: false + }, + propertyNames: { + pattern: ""^.?[a-zA-Z0-9]+$"" + }, + _plugin: true, +- _example: { ""rb"" => ""/usr/bin/ruby"" } ++ _example: { ""rb"" => [""/usr/bin/ruby"", ""-r"", ""puppet""], ++ "".py"" => ""/usr/bin/python3"" } + }, + ""job-poll-interval"" => { + type: Integer,",The `_example` field should be updated to include an interpreter with an array value. +235,"@@ -532,12 +532,14 @@ var supportedKeyTypes = map[string]acme.KeyType{ + + // Map of supported protocols. + // HTTP/2 only supports TLS 1.2 and higher. +-var supportedProtocols = map[string]uint16{ ++var SupportedProtocols = map[string]uint16{ + ""tls1.0"": tls.VersionTLS10, + ""tls1.1"": tls.VersionTLS11, + ""tls1.2"": tls.VersionTLS12, + } + ++// NOTE: if updating the above map, also update sslProtocolToStringMap in caddyhttp/fastcgi/fastcgi.go ++ + // Map of supported ciphers, used only for parsing config. + // + // Note that, at time of writing, HTTP/2 blacklists 276 cipher suites,",Put this in the godoc of SupportedProtocols instead. Preferably we would just use one map though. Why not just use this one? +236,"@@ -59,13 +59,12 @@ func (container *CronContainer) StopStatsCron() { + } + + // newCronContainer creates a CronContainer object. +-func newCronContainer(dockerID *string, name *string, dockerGraphPath string) *CronContainer { ++func newCronContainer(dockerID *string, dockerGraphPath string) *CronContainer { + statePath := filepath.Join(dockerGraphPath, DockerExecDriverPath, *dockerID) + + container := &CronContainer{ + containerMetadata: &ContainerMetadata{ + DockerID: dockerID, +- Name: name, + }, + statePath: statePath, + }","I'd feel a little safer if the first argument were a string, not a *string unless there's a particular reason for making it a pointer." +237,"@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; + import org.junit.Before; + import org.junit.Test; + ++import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.util.Arrays; + ",Can you please revert changes to files in the `thoughtworks` package? This is legacy code and we will eventually phase out RC. +238,"@@ -19,7 +19,10 @@ package org.openqa.selenium.grid.graphql; + + import graphql.schema.DataFetcher; + import graphql.schema.DataFetchingEnvironment; ++ ++import org.openqa.selenium.SessionNotCreatedException; + import org.openqa.selenium.grid.distributor.Distributor; ++import org.openqa.selenium.grid.sessionmap.SessionMap; + import org.openqa.selenium.internal.Require; + + import java.net.URI;",You can safely revert changes to this file. +239,"@@ -127,7 +127,6 @@ class AnchorHead(nn.Module): + + def loss_single(self, cls_score, bbox_pred, labels, label_weights, + bbox_targets, bbox_weights, num_total_samples, cfg): +- # classification loss + labels = labels.reshape(-1) + label_weights = label_weights.reshape(-1) + cls_score = cls_score.permute(0, 2, 3, 1).reshape(",This deletion is unnecessary. +240,"@@ -302,7 +302,10 @@ class Notification extends Component { + mdc-layout-grid__cell + mdc-layout-grid__cell--span-1 + ""> +- ++ { ++ typeof smallImage === 'string' ++ ? : smallImage ++ } +
+ } + ","I'm not a huge fan of this overloading of the prop; accepting very different types of arguments for props like this can be confusing, and wasn't part of the IB. I understand wanting to import the SVG directly, but the IB suggests using `${global._googlesitekitLegacyData.admin.assetsRoot}${userInputSuccessImage}` as the `src`/`smallImage` value here. It'd be great to refactor this to accept components directly in the future, but let's do that all-at-once rather than this hybrid approach that makes the API less clear." +241,"@@ -21,10 +21,7 @@ import java.io.InputStream; + import java.io.StringWriter; + import java.lang.invoke.MethodHandles; + import java.nio.charset.StandardCharsets; +-import java.util.Collections; +-import java.util.HashMap; +-import java.util.List; +-import java.util.Map; ++import java.util.*; + import java.util.concurrent.TimeUnit; + + import org.apache.solr.cloud.ZkController;","I've had this happen recently with IntelliJ, was this intentional?" +242,"@@ -22,9 +22,10 @@ + #include + #include + #include +-#include ++#include + #include ""vulkan/vulkan.h"" + #include ""vk_format_utils.h"" ++#include ""hash_util.h"" + + struct VULKAN_FORMAT_INFO { + size_t size;",Order(1) vs Order(logN) -- not sure it's measurable at the ~200 element size of the table. All of the published comparisons start at ~1000 elements. +243,"@@ -33,6 +33,7 @@ import ( + ""github.com/mysteriumnetwork/node/core/connection"" + ""github.com/mysteriumnetwork/node/core/ip"" + ""github.com/mysteriumnetwork/node/core/location"" ++ location_factory ""github.com/mysteriumnetwork/node/core/location/factory"" + ""github.com/mysteriumnetwork/node/core/node"" + ""github.com/mysteriumnetwork/node/core/port"" + ""github.com/mysteriumnetwork/node/core/service""",I don't know about this aliasing and 'factory'. Previous version was rather straightforward: `location.CreateLocationResolver`. Perhaps `location.CreateResolver` would be even better? What do we actually gain here from moving DI to a separate sub-package? +244,"@@ -47,6 +47,14 @@ void Engine::SetCallBack(std::function & /*variable*/, const char * /*values*/) {} + void Engine::Write(Variable & /*variable*/,",Use `UpperCamelCase` for function names +245,"@@ -232,9 +232,12 @@ SchemaDate.prototype.cast = function(value) { + + if (value instanceof Number || typeof value === 'number') { + date = new Date(value); ++ } else if (typeof value === 'string' && !isNaN(Number(value)) && (Number(value) >= 275761 || Number(value) < 0)) { ++ // string representation of milliseconds take this path ++ date = new Date(Number(value)); + } else if (typeof value.valueOf === 'function') { +- // support for moment.js. This is also the path strings will take because strings +- // have a `valueOf()` ++ // support for moment.js. This is also the path string representation of years ++ // will take because strings have a `valueOf()` + date = new Date(value.valueOf()); + } else { + // fallback","I'm not 100% sold on this idea but I like it in general. Nice compromise between using the 'Date' constructor where possible and falling back to the pre #5880 behavior when it makes sense. However, instead of `Number(value) < 0`, let's do `Number(value) < MIN_YEAR` because `new Date('-2017')` is perfectly valid in JS and I don't want to break the date behavior." +246,"@@ -138,8 +138,7 @@ public abstract class BaseHttpClusterStateProvider implements ClusterStateProvid + Set liveNodes = new HashSet((List)(cluster.get(""live_nodes""))); + this.liveNodes = liveNodes; + liveNodesTimestamp = System.nanoTime(); +- //TODO SOLR-11877 we don't know the znode path; CLUSTER_STATE is probably wrong leading to bad stateFormat +- ClusterState cs = ClusterState.load(znodeVersion, collectionsMap, liveNodes, ZkStateReader.CLUSTER_STATE); ++ ClusterState cs = ClusterState.createFromData(znodeVersion, collectionsMap, liveNodes); + if (clusterProperties != null) { + Map properties = (Map) cluster.get(""properties""); + if (properties != null) {",Remember to close SOLR-11877 after this +247,"@@ -1124,7 +1124,7 @@ void Identifier::_exportToJSON(JSONFormatter *formatter) const { + //! @cond Doxygen_Suppress + static bool isIgnoredChar(char ch) { + return ch == ' ' || ch == '_' || ch == '-' || ch == '/' || ch == '(' || +- ch == ')' || ch == '.' || ch == '&' || ch == ','; ++ ch == ')' || ch == '.' || ch == '&'; + } + //! @endcond + ",this change should be reverted +248,"@@ -186,9 +186,15 @@ type mockedIdentityRegistry struct { + anyIdentityRegistered bool + } + ++// IsRegistered mock + func (mir *mockedIdentityRegistry) IsRegistered(address common.Address) (bool, error) { + return mir.anyIdentityRegistered, nil + } + ++// WaitForRegistrationEvent mock ++func (mir *mockedIdentityRegistry) WaitForRegistrationEvent(providerAddress common.Address, registeredEvent chan int, stopLoop chan int) { ++ ++} ++ + //check that we implemented mocked registry correctly + var _ registry.IdentityRegistry = &mockedIdentityRegistry{}","This function signature is a bit complicated, some parameters are IN type (stopLoop which is modified from outside), others are OUT (registeredEvent channel which is modified inside function) I suggest the following signature -> SubscribeToRegistrationEvent(identityAddress) returns registeredEvent chan of type (RegisteredEvent not int), Unsubscribe func(), error (in case of any error). That way caller can always cance subscription if needed and check for any errors. Also - unsubscribe function hides any internal details how subscribtion is really implemented" +249,"@@ -45,7 +45,7 @@ const options = { + query: ['src/**/*.png', 'src/**/*.jpg', 'src/**/*.gif', 'src/**/*.svg'] + }, + copy: { +- query: ['src/**/*.json', 'src/**/*.ico'] ++ query: ['src/**/*.json', 'src/**/*.ico', 'src/**/*.wav'] + }, + injectBundle: { + query: 'src/index.html'","`.wav`?! cannot we use something slightly more modern and compressed instead? :) I dunno, like `.mp3` or `.aac` or `.ogg`..." +250,"@@ -1602,6 +1602,17 @@ luaA_client_swap(lua_State *L) + *ref_swap = c; + + luaA_class_emit_signal(L, &client_class, ""list"", 0); ++ ++ luaA_object_push(L, swap); ++ lua_pushboolean(L, true); ++ luaA_object_emit_signal(L, -4, ""swapped"", 2); ++ lua_pop(L, 2); ++ ++ luaA_object_push(L, swap); ++ luaA_object_push(L, c); ++ lua_pushboolean(L, false); ++ luaA_object_emit_signal(L, -3, ""swapped"", 2); ++ lua_pop(L, 3); + } + + return 0;",Wouldn't a single signal call be enough? (without the boolean even) +251,"@@ -17,6 +17,11 @@ +
+ <%= note_event(@note.status, @note.closed_at, @note_comments.last.author) %> + <% end %> ++ <% if current_user && current_user != @note.author %> ++ <%= link_to new_report_url(reportable_id: @note.id, reportable_type: @note.class.name), :title => t('browse.note.report') do %> ++  ⚐ ++ <% end %> ++ <% end %> +
+ + <% if @note_comments.find { |comment| comment.author.nil? } -%>","I suspect that this whole block, which is going to be repeated a number of times, should probably be in a helper. I guess it would need to be given the object and the title and could probably figure out everything else from that?" +252,"@@ -218,6 +218,9 @@ class Document < AbstractBlock + # Public: Get the Reader associated with this document + attr_reader :reader + ++ # Public: Get/Set the PathResolver instance used to resolve paths in this Document. ++ attr_reader :path_resolver ++ + # Public: Get the Converter associated with this document + attr_reader :converter + ",Should we expose this attribute in the Asciidoctor.js API ? +253,"@@ -147,7 +147,7 @@ public interface Multimap extends Traversable>, Function1 element) { +- return get(element._1).map(v -> Objects.equals(v, element._2)).getOrElse(false); ++ return get(element._1).map(v -> v.contains(element._2)).getOrElse(false); + } + + /**",I think contains on `Multimap` was broken - it should return true if one of the values is associated with the key? It that right +254,"@@ -57,6 +57,7 @@ public class TiConfiguration implements Serializable { + private static final int DEF_KV_CLIENT_CONCURRENCY = 10; + private static final List DEF_ISOLATION_READ_ENGINES = + ImmutableList.of(TiStoreType.TiKV, TiStoreType.TiFlash); ++ private static final int DEF_PREWRITE_CONCURRENCY = 20; + + private int timeout = DEF_TIMEOUT; + private TimeUnit timeoutUnit = DEF_TIMEOUT_UNIT;",delete this line +255,"@@ -43,6 +43,7 @@ module Test + + def self.setup_models + conn = ClientRequest.connection ++ return if conn.table_exists? ""test_client_requests"" + conn.create_table(:test_client_requests, force: true) do |t| + t.decimal :amount + t.string :project_title",Presumably we no longer need `force: true` here. +256,"@@ -339,6 +339,12 @@ hipError_t hipHostAlloc(void** ptr, size_t sizeBytes, unsigned int flags) { + // width in bytes + hipError_t ihipMallocPitch(void** ptr, size_t* pitch, size_t width, size_t height, size_t depth) { + hipError_t hip_status = hipSuccess; ++ if(ptr==NULL || ptr==0) ++ { ++ hip_status=hipErrorInvalidValue; ++ return hip_status; ++ } ++ + // hardcoded 128 bytes + *pitch = ((((int)width - 1) / 128) + 1) * 128; + const size_t sizeBytes = (*pitch) * height;",HIP runtime is compiled using a C++ compiler. So comparison to both NULL as well as 0 does not make sense. Just comparing to NULL is sufficient. +257,"@@ -0,0 +1,10 @@ ++<%= t(""mailer.welcome_mailer.welcome_notification.header"") %> ++ ++<%= t(""mailer.welcome_mailer.welcome_notification.para1"") %> ++ ++<%= t(""mailer.welcome_mailer.welcome_notification.para2"", help_url: help_url('') ) %> ++ ++<%= t(""mailer.welcome_mailer.welcome_notification.para3"", feedback_url: feedback_url ) %> ++ ++<%= t(""mailer.welcome_mailer.welcome_notification.signature"") %> ++",these urls are still in `a` tags so we should probably include these links separately for a non-HTML version +258,"@@ -507,8 +507,18 @@ func (s *Server) configureAccounts() error { + if opts.SystemAccount != _EMPTY_ { + // Lock may be acquired in lookupAccount, so release to call lookupAccount. + s.mu.Unlock() +- _, err := s.lookupAccount(opts.SystemAccount) ++ acc, err := s.lookupAccount(opts.SystemAccount) + s.mu.Lock() ++ if err == nil && s.sys != nil && acc != s.sys.account { ++ // sys.account.clients (including internal client)/respmap/etc... are transferred separately ++ s.sys.account = acc ++ s.mu.Unlock() ++ // acquires server lock separately ++ s.addSystemAccountExports(acc) ++ // can't hold the lock as go routine reading it may be waiting for lock as well ++ s.sys.resetCh <- struct{}{} ++ s.mu.Lock() ++ } + if err != nil { + return fmt.Errorf(""error resolving system account: %v"", err) + }","That's fine though, meaning that you can send to this channel under the server lock. The internalSendLoop will pick up the change when the server lock is released (if loop is blocked trying to grab the server lock). Even the way you do it here (releasing the lock, sending, then reacquiring) does not guarantee that the internalSendLoop will have time to refresh in that interval." +259,"@@ -47,6 +47,7 @@ public interface CapabilityType { + String ELEMENT_SCROLL_BEHAVIOR = ""elementScrollBehavior""; + String HAS_TOUCHSCREEN = ""hasTouchScreen""; + String OVERLAPPING_CHECK_DISABLED = ""overlappingCheckDisabled""; ++ String ENABLE_DOWNLOADING = ""chromium:enableDownloading""; + + String LOGGING_PREFS = ""loggingPrefs""; + ",The name `enableDownloading` implies this is a boolean capability. How about `downloadDir`? +260,"@@ -28,10 +28,9 @@ public interface ValidatorManager { + Map validate(Project project, File projectDir); + + /** +- * The ValidatorManager should have a default validator which checks for the most essential +- * components of a project. The ValidatorManager should always load the default validator. This +- * method returns the default validator of this ValidatorManager. ++ * ValidatorManager will not have any default validator. + */ ++ @Deprecated + ProjectValidator getDefaultValidator(); + + /**",Found one internal team is using this method. Will coordinate with them about the migration solution. +261,"@@ -230,6 +230,18 @@ namespace Datadog.Trace.Configuration + /// + public const string DiagnosticSourceEnabled = ""DD_DIAGNOSTIC_SOURCE_ENABLED""; + ++ /// ++ /// Configuration key for the application's server http statuses to set spans as errors by. ++ /// ++ /// ++ public const string HttpServerErrorCodes = ""DD_HTTP_SERVER_ERROR_STATUSES""; ++ ++ /// ++ /// Configuration key for the application's client http statuses to set spans as errors by. ++ /// ++ /// ++ public const string HttpClientErrorCodes = ""DD_HTTP_CLIENT_ERROR_STATUSES""; ++ + /// + /// String format patterns used to match integration-specific configuration keys. + /// ",The field `HttpServerErrorCodes` should be called `HttpServerErrorStatuses` +262,"@@ -35,6 +35,12 @@ MAXIMUM_LOOP_COUNT = 600 + DEFAULT_BUCKET_FMT_V1 = 'gs://{}-data-{}' + DEFAULT_BUCKET_FMT_V2 = 'gs://{}-{}-data-{}' + ++FORSETI_V1_RULE_FILES = [ ++ 'bigquery_rules.yaml', 'blacklist_rules.yaml', 'bucket_rules.yaml', ++ 'cloudsql_rules.yaml', 'firewall_rules.yaml', 'forwarding_rules.yaml', ++ 'group_rules.yaml', 'iam_rules.yaml', 'iap_rules.yaml', 'ke_rules.yaml', ++ 'instance_network_interface_rules.yaml'] ++ + GCLOUD_MIN_VERSION = (180, 0, 0) + GCLOUD_VERSION_REGEX = r'Google Cloud SDK (.*)' + GCLOUD_ALPHA_REGEX = r'alpha.*'","Can you please make each of these in a separate line. It will be easier to keep them sorted, and add/remove." +263,"@@ -170,10 +170,14 @@ public class ConfigSetsHandler extends RequestHandlerBase implements PermissionN + + boolean overwritesExisting = zkClient.exists(configPathInZk, true); + +- if (overwritesExisting && !req.getParams().getBool(ConfigSetParams.OVERWRITE, false)) { +- throw new SolrException(ErrorCode.BAD_REQUEST, +- ""The configuration "" + configSetName + "" already exists in zookeeper""); +- } ++ // Get upload parameters ++ String singleFilePath = req.getParams().get(ConfigSetParams.FILE_PATH, """"); ++ boolean allowOverwrite = req.getParams().getBool(ConfigSetParams.OVERWRITE, false); ++ // Cleanup is not allowed while using singleFilePath upload ++ boolean cleanup = singleFilePath.isEmpty() && req.getParams().getBool(ConfigSetParams.CLEANUP, false); ++ ++ // Create a node for the configuration in zookeeper ++ createBaseZnode(zkClient, overwritesExisting, isTrusted(req, coreContainer.getAuthenticationPlugin()), cleanup, configPathInZk); + + Iterator contentStreamsIterator = req.getContentStreams().iterator(); + ","should we error instead of silently ignoring the `cleanup` param? it defaults to `false`, so someone must have explicitly set it to `true`" +264,"@@ -191,7 +191,7 @@ func NewReader(r io.ReaderAt, size int64) (*Reader, error) { + if len(archive.File) == 0 { + return nil, errors.New(""archive is empty"") + } else if fi := archive.File[0].FileInfo(); !fi.IsDir() { +- return nil, errors.New(""archive root is not a directory"") ++ return nil, fmt.Errorf(""archive root directory missing: expected a 'root' directory but got %v"", archive.File[0].Name) + } + root := archive.File[0].Name + pref, err := unitPrefix(root, archive.File)","There is no specific requirement that the root be called `root`, just that there is a single root directory and that it be the first entry in the zip." +265,"@@ -1,6 +1,9 @@ + <% unless ENV['DISABLE_SANDBOX_WARNING'] == 'true' %> + <%= render partial: 'shared/sandbox_warning' %> + <% end %> ++<% if !current_page?(me_path) && current_user && current_user.requires_profile_attention? %> ++ <%= render partial: ""shared/user_profile_warning"" %> ++<% end %> +
+
+
",perhaps we should encapsulate this logic in a helper method w a test? +266,"@@ -0,0 +1,7 @@ ++[ 'options_hash', 'defaults', 'command_line_parser', 'pe_version_scraper', 'parser' ].each do |file| ++ begin ++ require ""beaker/options/#{file}"" ++ rescue LoadError ++ require File.expand_path(File.join(File.dirname(__FILE__), 'options', file)) ++ end ++end",Now that we're only using this repo as a Gem you shouldn't need to `require` an expanded local file path like below. +267,"@@ -53,7 +53,8 @@ enum Timestamps implements Transform { + OffsetDateTime timestamp = Instant + .ofEpochSecond(timestampMicros / 1_000_000) + .atOffset(ZoneOffset.UTC); +- return (int) granularity.between(EPOCH, timestamp); ++ Integer year = Long.valueOf(granularity.between(EPOCH, timestamp)).intValue(); ++ return year; + } + + @Override","This isn't necessarily a year. It may be months, days, or hours. Can we return `intValue()` directly instead?" +268,"@@ -351,8 +351,6 @@ func (mtask *managedTask) waitEvent(stopWaiting <-chan struct{}) bool { + mtask.handleDesiredStatusChange(acsTransition.desiredStatus, acsTransition.seqnum) + return false + case dockerChange := <-mtask.dockerMessages: +- seelog.Infof(""Managed task [%s]: got container [%s (Runtime ID: %s)] event: [%s]"", +- mtask.Arn, dockerChange.container.Name, dockerChange.container.GetRuntimeID(), dockerChange.event.Status.String()) + mtask.handleContainerChange(dockerChange) + return false + case resChange := <-mtask.resourceStateChangeEvent:",this is redundant because it gets logged immediately on entering the handleContainerChange function +269,"@@ -126,7 +126,7 @@ func (e *Executor) reportRequiringApproval(ctx context.Context) { + var approvers []string + + for _, v := range ds.GenericDeploymentConfig.DeploymentNotification.Mentions { +- if v.Event == ""DEPLOYMENT_WAIT_APPROVAL"" { ++ if e := ""EVENT_"" + v.Event; e == model.NotificationEventType_EVENT_DEPLOYMENT_WAIT_APPROVAL.String() { + approvers = v.Slack + } + }",`ds.GenericDeploymentConfig.DeploymentNotification` in L128 is nullable. +270,"@@ -42,4 +42,8 @@ public class CliqueMiningTracker { + public boolean blockCreatedLocally(final BlockHeader header) { + return CliqueHelpers.getProposerOfBlock(header).equals(localAddress); + } ++ ++ public ProtocolContext getProtocolContext() { ++ return protocolContext; ++ } + }",this shouldn't be exposed here - this class isn't a carriage for this - its used internally to determine if/how we can mine. +271,"@@ -265,13 +265,11 @@ public class FirefoxDriver extends RemoteWebDriver + + @Override + public String installExtension(Path path) { +- Require.nonNull(""Path"", path); + return extensions.installExtension(path); + } + + @Override + public void uninstallExtension(String extensionId) { +- Require.nonNull(""Extension ID"", extensionId); + extensions.uninstallExtension(extensionId); + } + ","It's fine to leave these checks in. It'll make the exception come from `FirefoxDriver`, and that's probably clearer to a user." +272,"@@ -60,8 +60,9 @@ RSpec.configure do |config| + # Add modules for helpers + config.include ControllerSpecHelper, type: :controller + config.include RequestSpecHelper, type: :request +- [:feature, :request].each do |type| ++ [:feature, :request, :model].each do |type| + config.include IntegrationSpecHelper, type: type ++ config.include EnvironmentSpecHelper, type: type + end + config.include FeatureSpecHelper, type: :feature + ","We don't want to include the `IntegrationSpecHelper` for models...mind moving this line out of the loop to be `config.include EnvironmentSpecHelper, type: :model`?" +273,"@@ -25,6 +25,9 @@ func TestWriteDrupalConfig(t *testing.T) { + err = WriteDrupalConfig(drupalConfig, file.Name()) + assert.NoError(t, err) + ++ os.Chmod(dir, 0755) ++ os.Chmod(file.Name(), 0666) ++ + err = os.RemoveAll(dir) + assert.NoError(t, err) + }",Please check the return on these. +274,"@@ -279,10 +279,14 @@ class Storage { + if (uplink == null) { + uplink = new Proxy({ + url: file.url, ++ cache: true, + _autogenerated: true, + }, self.config); + } +- let savestream = self.local.add_tarball(name, filename); ++ let savestream = null; ++ if (uplink.config.cache) { ++ savestream = self.local.add_tarball(name, filename); ++ } + let on_open = function() { + // prevent it from being called twice + on_open = function() {};",Do we need `==` for true? +275,"@@ -17,7 +17,7 @@ class BaseEMAHook(Hook): + momentum (float): The momentum used for updating ema parameter. + Ema's parameter are updated with the formula: + `ema_param = (1-momentum) * ema_param + momentum * cur_param`. +- Defaults to 0.0002. ++ Defaults to 0.0001. + skip_buffers (bool): Whether to skip the model buffers, such as + batchnorm running stats (running_mean, running_var), it does not + perform the ema operation. Default to False.",Changing the default value may cause BC-breaking. Suggest changing this value in config. +276,"@@ -325,7 +325,7 @@ class SimpleConfig(Logger): + slider_pos = max(slider_pos, 0) + slider_pos = min(slider_pos, len(FEE_ETA_TARGETS)) + if slider_pos < len(FEE_ETA_TARGETS): +- num_blocks = FEE_ETA_TARGETS[slider_pos] ++ num_blocks = FEE_ETA_TARGETS[int(slider_pos)] + fee = self.eta_target_to_fee(num_blocks) + else: + fee = self.eta_target_to_fee(1)",how does that happen? +277,"@@ -31,9 +31,9 @@ + # + from __future__ import print_function + +-import unittest ++import unittest, doctest + import os,sys +- ++from rdkit.six import exec_ + from rdkit.six.moves import cPickle + + from rdkit import rdBase",This is gross/clever. :-) +278,"@@ -1,6 +1,6 @@ + require File.expand_path(File.dirname(__FILE__) + '/test_helper.rb') + +-class TestZhCnLocale < Test::Unit::TestCase ++class TestZhLocale < Test::Unit::TestCase + def setup + Faker::Config.locale = 'zh-CN' + end",Take a look at the name of this file. Definitely copy and +279,"@@ -163,12 +163,15 @@ func NewVolumeInfo(URL string, volname string, namespace string) (volInfo *Volum + if resp.StatusCode == 500 { + fmt.Printf(""Volume: %s not found at namespace: %q\n"", volname, namespace) + err = util.InternalServerError ++ return + } else if resp.StatusCode == 503 { + fmt.Printf(""maya apiservice not reachable at %q\n"", mapiserver.GetURL()) + err = util.ServerUnavailable ++ return + } else if resp.StatusCode == 404 { + fmt.Printf(""Volume: %s not found at namespace: %q error: %s\n"", volname, namespace, http.StatusText(resp.StatusCode)) + err = util.PageNotFound ++ return + } + fmt.Printf(""Received an error from maya apiservice: statuscode: %d"", resp.StatusCode) + err = fmt.Errorf(""Received an error from maya apiservice: statuscode: %d"", resp.StatusCode)",Can you check with @mahebbar how to work this error. Should be different from 404. +280,"@@ -46,7 +46,7 @@ setup( + 'spark': ['pyspark>=2.4.0'], + 'mlflow': ['mlflow>=1.0'], + }, +- python_requires='>=3.5,<3.8', ++ python_requires='>=3.5', + install_requires=[ + 'pandas>=0.23.2', + 'pyarrow>=0.10',",Do we still need the upper bound `<3.9`? +281,"@@ -229,7 +229,10 @@ function getPathsToCheck($f_paths): ?array + /** @var string */ + $input_path = $input_paths[$i]; + +- if (realpath($input_path) === realpath(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'psalm') ++ if ( ++ realpath($input_path) === realpath(dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'psalm') ++ || realpath($input_path) === realpath(dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'psalter') ++ || realpath($input_path) === realpath(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'psalm') + || realpath($input_path) === realpath(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'psalter') + || realpath($input_path) === realpath(Phar::running(false)) + ) {",Does this mean `vendor/bin/psalm` is not a symlink (or whatever equivalent Windows has for symlinks) on Windows? +282,"@@ -1,4 +1,4 @@ +-package aws_test ++package aws + + import ( + ""fmt""","@lpabon having a separate package name `aws_test` allows to test the package as if the tester was an external package. If the test package name is the same as the package being tested, the test package can also use methods and variables not exposed to the eventual user." +283,"@@ -54,8 +54,6 @@ func RunEndToEndTest(ctx context.Context, t *testing.T, exp *otlpmetric.Exporter + instruments := map[string]data{ + ""test-int64-counter"": {sdkapi.CounterInstrumentKind, number.Int64Kind, 1}, + ""test-float64-counter"": {sdkapi.CounterInstrumentKind, number.Float64Kind, 1}, +- ""test-int64-histogram"": {sdkapi.HistogramInstrumentKind, number.Int64Kind, 2}, +- ""test-float64-histogram"": {sdkapi.HistogramInstrumentKind, number.Float64Kind, 2}, + ""test-int64-gaugeobserver"": {sdkapi.GaugeObserverInstrumentKind, number.Int64Kind, 3}, + ""test-float64-gaugeobserver"": {sdkapi.GaugeObserverInstrumentKind, number.Float64Kind, 3}, + }","The exporter should still be able to test these histogram instrument kinds, right? Is there another reason to remove these?" +284,"@@ -274,6 +274,13 @@ func (eval *BlockEvaluator) Round() basics.Round { + return eval.block.Round() + } + ++// ResetTxnBytes resets the number of bytes tracked by the BlockEvaluator to ++// zero. This is a specialized operation used by the transaction pool to ++// simulate the effect of putting pending transactions in multiple blocks. ++func (eval *BlockEvaluator) ResetTxnBytes(validateTxnBytes bool) { ++ eval.totalTxBytes = 0 ++} ++ + // Transaction tentatively adds a new transaction as part of this block evaluation. + // If the transaction cannot be added to the block without violating some constraints, + // an error is returned and the block evaluator state is unchanged.",should this increment eval.Round somehow? +285,"@@ -91,7 +91,7 @@ class Blacklight::Solr::Response < ActiveSupport::HashWithIndifferentAccess + value.each { |v| force_to_utf8(v) } + when String + if value.encoding != Encoding::UTF_8 +- Rails.logger.warn ""Found a non utf-8 value in Blacklight::Solr::Response. \""#{value}\"" Encoding is #{value.encoding}"" ++ Blacklight.logger.warn ""Found a non utf-8 value in Blacklight::Solr::Response. \""#{value}\"" Encoding is #{value.encoding}"" + value.dup.force_encoding('UTF-8') + else + value",Although this change looks good. Maybe there are other inconsistent cases too? +286,"@@ -21,7 +21,7 @@ module ApplicationHelper + '/auth/github' + end + +- def format_resources(resources) ++ def format_markdown(resources) + BlueCloth.new(resources).to_html.html_safe + end + ",This is a way better method name. +287,"@@ -1,7 +1,5 @@ + class NewLanguageConfirmationsController < ApplicationController + def index +- redirect_to welcome_to_upcase_path( +- confirmation: true, language_selected: params[:language], +- ), notice: ""Thanks for signing up. We will be in touch!"" ++ redirect_to root_path, notice: t(""marketing.show.language_flash"") + end + end",Prefer single-quoted strings when you don't need string interpolation or special symbols. +288,"@@ -1,3 +1,5 @@ ++options = Array.isArray(options) ? options : []; ++ + var invalid = []; + + var attr, attrName, allowed,","I was wondering if this should allow per role specification, instead of (or in addition to) a generic ""allowed everywhere"". So you could do: `{ separator: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax'] }`. You could still allow the array, and you could add a wildcard option for the ""generic"" case you've got now: `{ '*': ['always-allowed'] }`." +289,"@@ -942,7 +942,8 @@ SQLVarChar::SQLVarChar(Lng32 maxLen, + FALSE, allowSQLnull, isUpShifted, isCaseInsensitive, + TRUE, cs, co, ce, + encoding, vcIndLen), +- clientDataType_(collHeap()) // Get heap from NABasicObject. Can't allocate on stack. ++ clientDataType_(collHeap()), // Get heap from NABasicObject. Can't allocate on stack. ++ wasHiveString_(FALSE) + {} + #pragma warn(1506) // warning elimination + ",I'm confused by the name. The string was a Hive string but it isn't any longer? Why should we care? (I imagine I'll find the answer later... there is some different semantic that we want downstream...) +290,"@@ -31,12 +31,7 @@ import org.openqa.selenium.grid.sessionmap.SessionMap; + import org.openqa.selenium.grid.sessionmap.local.LocalSessionMap; + import org.openqa.selenium.netty.server.NettyServer; + import org.openqa.selenium.remote.SessionId; +-import org.openqa.selenium.remote.http.HttpClient; +-import org.openqa.selenium.remote.http.HttpHandler; +-import org.openqa.selenium.remote.http.HttpRequest; +-import org.openqa.selenium.remote.http.HttpResponse; +-import org.openqa.selenium.remote.http.TextMessage; +-import org.openqa.selenium.remote.http.WebSocket; ++import org.openqa.selenium.remote.http.*; + import org.openqa.selenium.remote.tracing.DefaultTestTracer; + import org.openqa.selenium.remote.tracing.Tracer; + ",Could you please leave the explicit imports? +291,"@@ -23,7 +23,7 @@ import ( + ""github.com/iotexproject/iotex-core/pkg/hash"" + ""github.com/iotexproject/iotex-core/pkg/keypair"" + ""github.com/iotexproject/iotex-core/pkg/log"" +- ""github.com/iotexproject/iotex-core/proto"" ++ iproto ""github.com/iotexproject/iotex-core/proto"" + ""github.com/iotexproject/iotex-core/state/factory"" + ) + ",Why need alias? +292,"@@ -148,6 +148,10 @@ func (c testTLFJournalConfig) teamMembershipChecker() kbfsmd.TeamMembershipCheck + return nil + } + ++func (c testTLFJournalConfig) tlfIDGetter() tlfIDGetter { ++ return nil ++} ++ + func (c testTLFJournalConfig) diskLimitTimeout() time.Duration { + return c.dlTimeout + }","Shouldn't this be a `libfs.nullIDGetter` (exported, of course)?" +293,"@@ -156,6 +156,9 @@ const ( + tealsignTooManyArg = ""--set-lsig-arg-idx too large, maximum of %d arguments"" + tealsignInfoWroteSig = ""Wrote signature for %s to LSig.Args[%d]"" + ++ tealLogicSigSize = ""%s: logicsig program size too large: %d > %d"" ++ tealAppSize = ""%s: app program size too large: %d > %d"" ++ + // Wallet + infoRecoveryPrompt = ""Please type your recovery mnemonic below, and hit return when you are done: "" + infoChoosePasswordPrompt = ""Please choose a password for wallet '%s': """,I dislike the messages.go pattern; the strings are only used once and make more sense in context. The other two added reportErrorf() calls in clerk.go have inline strings. +294,"@@ -118,9 +118,6 @@ Status FetchVerticesExecutor::prepareTags() { + if (!tagIdStatus.ok()) { + return tagIdStatus.status(); + } +- auto tagId = tagIdStatus.value(); +- tagNames_.push_back(tagName); +- tagIds_.push_back(tagId); + auto result = tagNameSet_.emplace(tagName); + if (!result.second) { + return Status::Error(folly::sformat(""tag({}) was dup"", tagName));",Seems we don't need it anymore. +295,"@@ -54,7 +54,7 @@ class Guidance < ActiveRecord::Base + validates :published, inclusion: { message: INCLUSION_MESSAGE, + in: BOOLEAN_VALUES} + +- validates :themes, presence: { message: PRESENCE_MESSAGE } ++ validates :themes, presence: { message: PRESENCE_MESSAGE }, if: :published? + + # Retrieves every guidance associated to an org + scope :by_org, -> (org) {",This might cause problems with the weird way we publish Guidance and Groups in the UI. We will have to make sure that UAT is thorough. +296,"@@ -75,7 +75,7 @@ func NewRawExporter(config Config) (*Exporter, error) { + // defer pipeline.Stop() + // ... Done + func InstallNewPipeline(config Config) (*push.Controller, error) { +- controller, err := NewExportPipeline(config) ++ controller, err := NewExportPipeline(config, time.Hour) + if err != nil { + return controller, err + }","this default needs to be on order 1 minute, I'm not sure why we defaulted to 1 hour below..." +297,"@@ -92,6 +92,15 @@ func (ACMEIssuer) CaddyModule() caddy.ModuleInfo { + func (iss *ACMEIssuer) Provision(ctx caddy.Context) error { + iss.logger = ctx.Logger(iss) + ++ // expand email address, if non-empty ++ if iss.Email != """" { ++ email, err := caddy.NewReplacer().ReplaceOrErr(iss.Email, true, true) ++ if err != nil { ++ return fmt.Errorf(""expanding email address '%s': %v"", iss.Email, err) ++ } ++ iss.Email = email ++ } ++ + // DNS providers + if iss.Challenges != nil && iss.Challenges.DNS != nil && iss.Challenges.DNS.ProviderRaw != nil { + val, err := ctx.LoadModule(iss.Challenges.DNS, ""ProviderRaw"")","I figure to make `{env.*}` work, right? I can't think of any other placeholder that makes sense here" +298,"@@ -29,7 +29,9 @@ TestEnv::~TestEnv() { + void TestEnv::SetUp() { + FLAGS_load_data_interval_secs = 1; + // Create metaServer +- metaServer_ = nebula::meta::TestUtils::mockMetaServer(0, metaRootPath_.path()); ++ metaServer_ = nebula::meta::TestUtils::mockMetaServer( ++ network::NetworkUtils::getAvailablePort(), ++ metaRootPath_.path()); + FLAGS_meta_server_addrs = folly::stringPrintf(""127.0.0.1:%d"", metaServerPort()); + + // Create storageServer",Why change the port from 0 to getAvailablePort()? +299,"@@ -691,9 +691,9 @@ class TestSeleniumScriptGeneration(SeleniumTestCase): + content = fds.read() + + target_lines = [ +- ""var_loc_keys=self.loc_mng.get_locator([{'name':'btn1',}])self.driver.find_element"" ++ ""var_loc_keys=self.loc_mng.get_locator([{'name':'btn1',}],30.0)self.driver.find_element"" + ""(var_loc_keys[0],var_loc_keys[1]).click()"", +- ""var_loc_keys=self.loc_mng.get_locator([{'id':'Id_123',}])self.driver.find_element"" ++ ""var_loc_keys=self.loc_mng.get_locator([{'id':'Id_123',}],30.0)self.driver.find_element"" + ""(var_loc_keys[0],var_loc_keys[1]).clear()"", + ""self.driver.find_element(var_loc_keys[0],var_loc_keys[1]).send_keys('London')"" + ]","For me would be great don't repeat timeout sending in every get_locator call. Looks like it should be sent into LocatorsManager init. And possibly it should me non mandatory, something like that: `def __init__ (self, locators, timeout=60):`" +300,"@@ -30,8 +30,9 @@ func NewGlobalOpts() *GlobalOpts { + bindProjectName() + + return &GlobalOpts{ +- projectName: viper.GetString(projectFlag), +- prompt: prompt.New(), ++ // Leave the projectName as empty in case it's overwritten by a global flag. ++ // See https://github.com/aws/amazon-ecs-cli-v2/issues/570#issuecomment-569133741 ++ prompt: prompt.New(), + } + } + ","I feel like since now we don't initiate the `opts.projectName` with `opts.ProjectName()`, which means `opts.projectName` and `opts.ProjectName()` they don't necessarily equal to each other, we need to also substitute all usage of `opts.ProjectName()` within `Ask()`, `Validate()`, and `Execute()` to `opts.projectName`. Otherwise if `-p` is set, `opts.ProjectName()` will get expired." +301,"@@ -531,7 +531,7 @@ namespace Nethermind.Core.Extensions + [DebuggerStepThrough] + public static string ByteArrayToHexViaLookup32Safe(byte[] bytes, bool withZeroX) + { +- if (bytes.Length == 0) ++ if (bytes?.Length == 0 || bytes == null) + { + return withZeroX ? ""0x"" : """"; + }",why do we thinkg that an empty string is ok to return from this method? I think the null should never be passed in here in the first place +302,"@@ -142,15 +142,12 @@ axe.utils.getNodeFromTree = function(vNode, node) { + return vNode; + } + vNode.children.forEach(candidate => { +- var retVal; +- +- if (candidate.actualNode === node) { ++ if (found) { ++ return; ++ } else if (candidate.actualNode === node) { + found = candidate; + } else { +- retVal = axe.utils.getNodeFromTree(candidate, node); +- if (retVal) { +- found = retVal; +- } ++ found = axe.utils.getNodeFromTree(candidate, node); + } + }); + return found;",nit: can remove this `else` since we return from the condition above. +303,"@@ -39,11 +39,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http + _flushCompleted = OnFlushCompleted; + } + +- public void Write(ArraySegment buffer, bool chunk = false) +- { +- WriteAsync(buffer, default(CancellationToken), chunk).GetAwaiter().GetResult(); +- } +- + public Task WriteAsync(ArraySegment buffer, bool chunk = false, CancellationToken cancellationToken = default(CancellationToken)) + { + if (cancellationToken.IsCancellationRequested)",You missed `Write(...)`! I'm kidding ofc. +304,"@@ -5,7 +5,7 @@ class SubscriptionUpcomingInvoiceUpdater + + def process + @subscriptions.each do |subscription| +- if subscription.stripe_customer_id ++ if subscription.stripe_customer_id.present? + upcoming_invoice = upcoming_invoice_for(subscription.stripe_customer_id) + update_next_payment_information(subscription, upcoming_invoice) + end",Was there a customer who had this set to an empty string? +305,"@@ -13,6 +13,14 @@ module Ncr + approver_email_address(final_approver) + end + ++ def status_aware_approver_email_address ++ if proposal.approved? ++ final_approver_email_address ++ else ++ current_approver_email_address ++ end ++ end ++ + private + + def approver_email_address(approver)","I know we have the `reporter` spec below, but what about a unit test for this to explain reasoning behind logic? If I were going to update this decorator, I would assume it wasn't covered by tests because there is no unit test." +306,"@@ -34,4 +34,6 @@ public interface RestClientRequest { + void addForm(String name, Object value); + + Buffer getBodyBuffer() throws Exception; ++ ++ void attach(String name, String filename); + }","it's better to be : void attach(String name, Part part);" +307,"@@ -77,7 +77,8 @@ public abstract class BasePageIterator { + protected abstract void initDefinitionLevelsReader(DataPageV1 dataPageV1, ColumnDescriptor descriptor, + ByteBufferInputStream in, int count) throws IOException; + +- protected abstract void initDefinitionLevelsReader(DataPageV2 dataPageV2, ColumnDescriptor descriptor); ++ protected abstract void initDefinitionLevelsReader(DataPageV2 dataPageV2, ColumnDescriptor descriptor) ++ throws IOException; + + public int currentPageCount() { + return triplesCount;","I didn't see where the IOException can get thrown, is this just to match the V1 reader?" +308,"@@ -418,7 +418,7 @@ unsigned int compute2DCoordsMimicDistMat( + RDKit::ROMol &mol, const DOUBLE_SMART_PTR *dmat, bool canonOrient, + bool clearConfs, double weightDistMat, unsigned int nFlipsPerSample, + unsigned int nSamples, int sampleSeed, bool permuteDeg4Nodes, +- bool forceRDKit) { ++ bool /* forceRDKit */) { + // storage for pieces of a molecule/s that are embedded in 2D + std::list efrags; + computeInitialCoords(mol, nullptr, efrags);",We normally suppress this warning with `RDUSED_PARAM(forceRDKit)` +309,"@@ -473,12 +473,11 @@ Player* Game::getPlayerByGUID(const uint32_t& guid) + return nullptr; + } + +- for (const auto& it : players) { +- if (guid == it.second->getGUID()) { +- return it.second; +- } ++ auto it = mappedPlayerGuids.find(guid); ++ if (it == mappedPlayerGuids.end()) { ++ return nullptr; + } +- return nullptr; ++ return it->second; + } + + ReturnValue Game::getPlayerByNameWildcard(const std::string& s, Player*& player)","What if `Game::getPlayerByNameWildcard` had not been called before. It would not find a player, wouldn't it?" +310,"@@ -129,7 +129,7 @@ public class ApplicationsSidebar extends Sidebar { + this.testingCheck = new SidebarCheckBox(tr(""Testing"")); + this.testingCheck.selectedProperty().bindBidirectional(filter.containTestingApplicationsProperty()); + +- this.requiresPatchCheck = new SidebarCheckBox(tr(""Requires patch"")); ++ this.requiresPatchCheck = new SidebarCheckBox(tr(""Patch Required"")); + this.requiresPatchCheck.selectedProperty().bindBidirectional(filter.containRequiresPatchApplicationsProperty()); + + this.commercialCheck = new SidebarCheckBox(tr(""Commercial""));","Why upper case ""R""?" +311,"@@ -107,3 +107,19 @@ func relativeDockerfilePath(ws copilotDirGetter, dockerfilePath string) (string, + } + return relDfPath, nil + } ++ ++// dfBuildRequired returns if the container image should be built from local Dockerfile. ++func dfBuildRequired(svc interface{}) (bool, error) { ++ type manifest interface { ++ BuildRequired() (bool, error) ++ } ++ mf, ok := svc.(manifest) ++ if !ok { ++ return false, fmt.Errorf(""service does not have required methods BuildRequired()"") ++ } ++ required, err := mf.BuildRequired() ++ if err != nil { ++ return false, fmt.Errorf(""check if service requires building from local Dockerfile: %w"", err) ++ } ++ return required, nil ++}","Does this need to return an error or could it return `false, nil`?" +312,"@@ -94,7 +94,7 @@ public abstract class Analyzer implements Closeable { + * Create a new Analyzer, reusing the same set of components per-thread + * across calls to {@link #tokenStream(String, Reader)}. + */ +- public Analyzer() { ++ protected Analyzer() { + this(GLOBAL_REUSE_STRATEGY); + } + ",Can you not change those scopes in public API classes? This applies here and in other places -- protected changed to package-scope for source is not really an API-compatible change. +313,"@@ -85,7 +85,7 @@ class TranslationsController extends BaseAdminController + 'item_to_translate' => $item_to_translate, + 'item_name' => $item_name, + 'module_part' => $module_part, +- 'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only', 1), ++ 'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only'), + 'max_input_vars_warning' => false, + ); + ","this parameter is only used in POST, please use `getRequest()->request->get('...');` Thanks" +314,"@@ -29,8 +29,8 @@ export default function(config: Config, auth: IAuth, storage: IStorageHandler) { + // this might be too harsh, so ask if it causes trouble + // $FlowFixMe + app.param('package', validatePackage); ++ app.param('filename', validatePackage); + // $FlowFixMe +- app.param('filename', validateName); + app.param('tag', validateName); + app.param('version', validateName); + app.param('revision', validateName);",Problem number 1: Scoped packages would have a `/` character here. Changing this to `validatePackage` resolves the 403. +315,"@@ -639,7 +639,11 @@ class LabelledData(param.Parameterized): + for k, v in self.items(): + new_val = v.map(map_fn, specs, clone) + if new_val is not None: +- deep_mapped[k] = new_val ++ # Ensure key validation doesn't cause errors ++ try: ++ deep_mapped[k] = new_val ++ except KeyError: ++ pass + if applies: deep_mapped = map_fn(deep_mapped) + return deep_mapped + else:",I don't quite get why there would be key errors: ``deep_mapped`` is a clone of ``self`` and ``k`` comes from ``self.items()`` so why would the key ever be rejected? +316,"@@ -427,6 +427,15 @@ func (te *transactorEndpoint) Withdraw(c *gin.Context) { + } + + chainID := config.GetInt64(config.FlagChainID) ++ if req.ChainID != 0 { ++ if _, ok := registry.Chains()[req.ChainID]; !ok { ++ utils.SendError(resp, errors.New(""Unsupported chain""), http.StatusBadRequest) ++ return ++ } ++ ++ chainID = req.ChainID ++ } ++ + err = te.promiseSettler.Withdraw(chainID, identity.FromAddress(req.ProviderID), common.HexToAddress(req.HermesID), common.HexToAddress(req.Beneficiary)) + if err != nil { + utils.SendError(resp, err, http.StatusInternalServerError)","this chain ID determines only from which chain to withdraw, therefore your changes do not accomplish what you want them to accomplish. You'll need changes to `func (aps *hermesPromiseSettler) Withdraw(chainID int64, providerID identity.Identity, hermesID, beneficiary common.Address) error`. The method probably has to include two chain ids: to and from. Currently, the method internally uses: `aps.config.L1ChainID` -> the chain to withdraw to `chainID` -> the chainID that was passed as the chain that the withdrawal is originating from." +317,"@@ -57,7 +57,11 @@ func (TraceContext) Inject(ctx context.Context, supplier propagation.HTTPSupplie + } + + func (tc TraceContext) Extract(ctx context.Context, supplier propagation.HTTPSupplier) context.Context { +- return ContextWithRemoteSpanContext(ctx, tc.extract(supplier)) ++ sc := tc.extract(supplier) ++ if !sc.IsValid() { ++ return ctx ++ } ++ return ContextWithRemoteSpanContext(ctx, sc) + } + + func (TraceContext) extract(supplier propagation.HTTPSupplier) core.SpanContext {","If instead we had `TraceContext.extract` return a bool value as a second return value, we could avoid the byte array comparison in `TraceID.IsValid`. Did you consider that alternative?" +318,"@@ -22,8 +22,8 @@ + #include ""depotchest.h"" + #include ""tools.h"" + +-DepotChest::DepotChest(uint16_t type) : +- Container(type), maxDepotItems(2000) {} ++DepotChest::DepotChest(uint16_t type, bool paginated /*= true*/) : ++ Container(type, items[type].maxItems, true, paginated), maxDepotItems(2000) {} + + ReturnValue DepotChest::queryAdd(int32_t index, const Thing& thing, uint32_t count, + uint32_t flags, Creature* actor/* = nullptr*/) const",here shouldn't we use `depotFreeLimit`? +319,"@@ -0,0 +1,3 @@ ++# A secret token used to encrypt user_id's in the Bookmarks#export callback URL ++# functionality, for example in Refworks export of Bookmarks. ++Rails.application.config.blacklight_export_secret_token = '<%= SecureRandom.hex(64) %>'",Could we use the Rails application's secret token instead? Do we actually need our own here? +320,"@@ -80,6 +80,10 @@ class GroupByTest(ReusedSQLTestCase, TestUtils): + + self.assertRaises(TypeError, lambda: kdf.a.groupby(kdf.b, as_index=False)) + ++ self.assertRaises(ValueError, lambda: kdf.groupby('a', axis=1)) ++ self.assertRaises(ValueError, lambda: kdf.groupby('a', 'b')) ++ self.assertRaises(TypeError, lambda: kdf.a.groupby(kdf.a, kdf.b)) ++ + # we can't use column name/names as a parameter `by` for `SeriesGroupBy`. + self.assertRaises(KeyError, lambda: kdf.a.groupby(by='a')) + self.assertRaises(KeyError, lambda: kdf.a.groupby(by=['a', 'b']))",so should be fixed here also +321,"@@ -6478,8 +6478,13 @@ dr_get_mcontext_priv(dcontext_t *dcontext, dr_mcontext_t *dmc, priv_mcontext_t * + * when most old clients have been converted, remove this (we'll + * still return false) + */ +- CLIENT_ASSERT(dmc->size == sizeof(dr_mcontext_t), +- ""dr_mcontext_t.size field not set properly""); ++ CLIENT_ASSERT( ++ dmc->size == sizeof(dr_mcontext_t) || ++ /* Opmask storage has been added for AVX-512 (xref i#1312). ++ * An older client's mcontext may be filled in w/o the new structure. ++ */ ++ dmc->size == sizeof(dr_mcontext_t) - sizeof(dr_opmask_t), ++ ""dr_mcontext_t.size field not set properly""); + CLIENT_ASSERT(dmc->flags != 0 && (dmc->flags & ~(DR_MC_ALL)) == 0, + ""dr_mcontext_t.flags field not set properly""); + } else",I would just remove this assert as it's going to get un-maintainable with a long list of valid sizes. Ditto below. +322,"@@ -28,6 +28,7 @@ func DefaultConfig() Config { + ReservedPorts: []uint16{SSHPort, DockerReservedPort, DockerReservedSSLPort, AgentIntrospectionPort, AgentCredentialsPort}, + ReservedPortsUDP: []uint16{}, + DataDir: ""/data/"", ++ HostDataDir: ""/var/lib/ecs/"", + DisableMetrics: false, + ReservedMemory: 0, + AvailableLoggingDrivers: []dockerclient.LoggingDriver{dockerclient.JSONFileDriver},",`HostDataDir` is misleading. Can we rename it to something more relevant ? The constant should also be moved up and reused as necessary. +323,"@@ -37,6 +37,9 @@ const ( + defaultMTUGRE = 1462 + defaultMTUSTT = 1500 + defaultMTU = 1500 ++ // IPsec ESP can add a maximum of 38 bytes to the packet including the ESP ++ // header and trailer. ++ ipsecESPOverhead = 38 + ) + + type Options struct {",I still feel like we are double-counting the outer IP header here (once in `defaultMTUGRE` and once in `ipsecESPOverhead`) but I'm not that familiar with IPsec. +324,"@@ -14,11 +14,15 @@ + // limitations under the License. + // + +-#nullable enable ++using System; ++using System.Collections.Generic; ++using System.Diagnostics.Metrics; + + namespace OpenTelemetry.Metrics + { + public abstract class MeasurementProcessor : BaseProcessor + { ++ public abstract void OnEnd(MeasurementItem measurementItem, ref DateTimeOffset dt, ref T value, ref ReadOnlySpan> tags) ++ where T : struct; + } + }","Not sure what benefit we gain by extending BaseProcessor here, as this seems to be defining a new OnEnd method. Could we modify MeasurementItem to have all the things, and then MeasurementProcessor can be simply extending BaseProcessor (not blocking. just noting some observations in the PR :) )" +325,"@@ -3,6 +3,13 @@ package cmd + import ( + ""bufio"" + ""fmt"" ++ ""io/ioutil"" ++ ""os"" ++ ""path"" ++ ""path/filepath"" ++ ""runtime"" ++ ""strings"" ++ + ""github.com/drud/ddev/pkg/ddevapp"" + ""github.com/drud/ddev/pkg/exec"" + ""github.com/drud/ddev/pkg/fileutil""",This change was not really intended but made by the linter of VS Code. And looking at other packages this looks like a best practise to place interal packages on the top and gh imports afterwards. +326,"@@ -51,7 +51,8 @@ type Options struct { + DefaultSamplingPolicy trace.Sampler + } + +-// New creates a new server. New(nil) is the same as new(Server). ++// New creates a new server. New(nil) is the same as new(Server). Note: A ++// configured Requestlogger will not log HealthChecks. + func New(opts *Options) *Server { + srv := new(Server) + if opts != nil {",This seems like a more appropriate message under `ListenAndServe`. WDYT? +327,"@@ -156,7 +156,6 @@ test.suite( + await driver.get(fileServer.Pages.basicAuth) + let source = await driver.getPageSource() + assert.strictEqual(source.includes('Access granted!'), true) +- await server.stop() + }) + }) + ",Is this not required? +328,"@@ -360,7 +360,16 @@ class AdminController extends Controller + } + + $searchableFields = $this->entity['search']['fields']; +- $paginator = $this->findBy($this->entity['class'], $this->request->query->get('query'), $searchableFields, $this->request->query->get('page', 1), $this->config['list']['max_results'], $this->request->query->get('sortField'), $this->request->query->get('sortDirection'), $this->entity['search']['dql_filter']); ++ $paginator = $this->findBy( ++ $this->entity['class'], ++ $this->request->query->get('query'), ++ $searchableFields, ++ $this->request->query->get('page', 1), ++ $this->config['list']['max_results'], ++ isset($this->entity['search']['sort']['field']) ? $this->entity['search']['sort']['field'] : $this->request->query->get('sortField'), ++ isset($this->entity['search']['sort']['direction']) ? $this->entity['search']['sort']['direction'] : $this->request->query->get('sortDirection'), ++ $this->entity['search']['dql_filter'] ++ ); + $fields = $this->entity['list']['fields']; + + $this->dispatch(EasyAdminEvents::POST_SEARCH, array(",We should start thinking of an object that encapsulates this information :) we might need more arguments in the future. +329,"@@ -4652,10 +4652,12 @@ TEST_F(VkLayerTest, RenderPassBarrierConflicts) { + img_barrier.subresourceRange.levelCount = 1; + // Mis-match src stage mask + m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, ""VUID-vkCmdPipelineBarrier-srcStageMask-01173""); ++ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, ""VUID-vkCmdPipelineBarrier-dstStageMask-01174""); + vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier); + m_errorMonitor->VerifyFound(); + // Now mis-match dst stage mask ++ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, ""VUID-vkCmdPipelineBarrier-srcStageMask-01173""); + m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, ""VUID-vkCmdPipelineBarrier-dstStageMask-01174""); + vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_HOST_BIT, + VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);","Given that we are (conceptually) searching across multiple self-dependencies, all we can say is that we didn't have a self dependency in which *both* source and dest masks were correct. Since the spec doesn't imagine this case, the valid usage statement assume we can differentiate only wrong source from only wrong dest within a *single* self-dependency -- which we can't across multiple (at least not meaningfully)... so we always return both the source/dest VUID's if we can't find a self-dependency in with *both* are correct." +330,"@@ -52,11 +52,11 @@ public class EthMiningTest { + public void shouldReturnTrueWhenMiningCoordinatorExistsAndRunning() { + final JsonRpcRequest request = requestWithParams(); + final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(request.getId(), true); +- when(miningCoordinator.isRunning()).thenReturn(true); ++ when(miningCoordinator.isMining()).thenReturn(true); + + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); +- verify(miningCoordinator).isRunning(); ++ verify(miningCoordinator).isMining(); + verifyNoMoreInteractions(miningCoordinator); + } + ",rename? MiningCoordinator always exists +331,"@@ -8,7 +8,8 @@ + var ip = {}, + net = require('net'), + extIP = require('external-ip'), +- plugins = require('../../../plugins/pluginManager.js'); ++ plugins = require('../../../plugins/pluginManager.js'), ++ offlineMode = plugins.getConfig(""api"").offline_mode; + + /** + * Function to get the hostname/ip address/url to access dashboard","Here would be the same case you don't need to call `loadConfigs`, but you would need to reread configs using `getConfig` on each getHost function call, not once per file." +332,"@@ -486,6 +486,8 @@ func (d *Dir) Cleanup(ctx context.Context, fi *dokan.FileInfo) { + defer func() { d.folder.reportErr(ctx, libkbfs.WriteMode, err) }() + + if fi != nil && fi.IsDeleteOnClose() && d.parent != nil { ++ d.folder.fs.renameAndDeletionLock.Lock() ++ defer d.folder.fs.renameAndDeletionLock.Unlock() + d.folder.fs.log.CDebugf(ctx, ""Removing (Delete) dir in cleanup %s"", d.name) + + err = d.folder.fs.config.KBFSOps().RemoveDir(ctx, d.parent, d.name)","Unlocking with defer means that this lock is still held curing the call to forgetNode(), below, which I see attempts to acquire `f.mu`, which looks dangerous to me." +333,"@@ -56,7 +56,7 @@ func Test_Mine(t *testing.T) { + baseBlock := &block.Block{Height: 2, StateRoot: stateRoot, Tickets: []block.Ticket{{VRFProof: []byte{0}}}} + tipSet := th.RequireNewTipSet(t, baseBlock) + +- st, pool, addrs, cst, bs := sharedSetup(t, mockSignerVal) ++ st, pool, addrs, _, bs := sharedSetup(t, mockSignerVal) + getStateTree := func(c context.Context, ts block.TipSet) (state.Tree, error) { + return st, nil + }",Does anyone still use the cst out of this method? If not consider deleting +334,"@@ -9,6 +9,7 @@ get( + ""/getting-started-with-ios-development?utm_source=podcast"" + ) + ) ++get ""/videos/vim-for-rails-developers"" => redirect(""https://www.youtube.com/watch?v=9J2OjH8Ao_A"") + get ""/humans-present/oss"" => redirect( ""https://www.youtube.com/watch?v=VMBhumlUP-A"") + get ""/ios-on-rails"" => redirect(""https://gumroad.com/l/ios-on-rails"") + get ""/ios-on-rails-beta"" => redirect(""https://gumroad.com/l/ios-on-rails"")",Line is too long. [97/80] +335,"@@ -1,12 +1,14 @@ + """""" Testing for data_transfer.py """""" + + ### Python imports ++from io import BytesIO + import pathlib + + from unittest import mock + + ### Third-party imports + from botocore.stub import ANY ++from botocore.exceptions import ReadTimeoutError + import pandas as pd + import pytest + ",This seems unused. +336,"@@ -184,8 +184,8 @@ func GetOSInterface() types.OSTypeInstaller { + case CentOSType: + return &CentOS{} + default: ++ panic(""unsupport os-release"") + } +- return nil + } + + //IsKubeEdgeController identifies if the node is having edge controller and k8s api-server already running.","@luguanglong , Thanks for the fix, can you re-phrase it to sound better something like ""This OS version is currently un-supported by keadm""" +337,"@@ -53,6 +53,10 @@ from rdkit.Chem.Draw import rdMolDraw2D + from rdkit.Chem import rdDepictor + from rdkit.Chem import rdMolDescriptors as rdMD + ++def _CleanFpInfoAttr_(mol): ++ if hasattr(mol, '_fpInfo'): ++ delattr(mol, '_fpInfo') ++ + + def GetAtomicWeightsForFingerprint(refMol, probeMol, fpFunction, metric=DataStructs.DiceSimilarity): + """"""",should probably be called `_DeleteFpInfoAttr` because it removes it. Cleaning gives the impression it is still there. I would also move this to the end of the function `GetAtomicWeightsForFingerprint`. +338,"@@ -7101,6 +7101,13 @@ bool CoreChecks::PreCallValidateCmdBindDescriptorSets(VkCommandBuffer commandBuf + ""(%zu) when pipeline layout was created"", + firstSet, setCount, pipeline_layout->set_layouts.size()); + } ++ ++ static const std::map bindpoint_errors = { ++ std::make_pair(VK_PIPELINE_BIND_POINT_GRAPHICS, ""VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361""), ++ std::make_pair(VK_PIPELINE_BIND_POINT_COMPUTE, ""VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361""), ++ std::make_pair(VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, ""VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361"")}; ++ skip |= ValidatePipelineBindPoint(cb_state, pipelineBindPoint, ""vkCmdBindPipeline()"", bindpoint_errors); ++ + return skip; + } + ","nit, can we use `VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR` here (granted it isn't else where, maybe worth fixing here or in separate PR)" +339,"@@ -23,6 +23,6 @@ class Api::V1::ExercisesController < ApiController + end + + def exercise_parameters +- params.require(:exercise).permit(:edit_url, :summary, :title, :url) ++ params.require(:exercise).permit(:edit_url, :summary, :name, :url) + end + end",This will need to be updated in the upcase-exercises repo as well. +340,"@@ -21,7 +21,7 @@ class Trail < ActiveRecord::Base + def steps_remaining_for(user) + ExerciseWithProgressQuery. + new(user: user, exercises: exercises). +- count { |exercise| exercise.state != Status::REVIEWED } ++ count { |exercise| exercise.state != Status::COMPLETE } + end + + def self.most_recent_published",Think it's worth extracting this to `Exercise#complete?`? +341,"@@ -87,14 +87,6 @@ class Currency + return $this->exchangeRate; + } + +- /** +- * @return string +- */ +- public function getReversedExchangeRate() +- { +- return 1 / $this->exchangeRate; +- } +- + /** + * @param string $exchangeRate + */",This is still a potentially useful public method - should we remove such methods? +342,"@@ -40,15 +40,9 @@ public abstract class ApiDefaultsConfig { + /** The name of the license of the client library. */ + public abstract String licenseName(); + +- protected abstract Map releaseLevel(); +- + /** The development status of the client library. Configured per language. */ +- public ReleaseLevel releaseLevel(TargetLanguage language) { +- ReleaseLevel level = releaseLevel().get(language); +- if (level == null) { +- level = ReleaseLevel.UNSET_RELEASE_LEVEL; +- } +- return level; ++ public ReleaseLevel releaseLevel() { ++ return ReleaseLevel.ALPHA; + } + + protected abstract Map generatedNonGAPackageVersionBound();","I don't understand this change, what is happening here?" +343,"@@ -944,7 +944,8 @@ class ExcelCellTextInfo(NVDAObjectTextInfo): + + def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True): + formatField=textInfos.FormatField() +- if (self.obj.excelCellObject.Application.Version > ""12.0""): ++ version=int(self.obj.excelCellObject.Application.Version.split('.')[0]) ++ if version>12: + cellObj=self.obj.excelCellObject.DisplayFormat + else: + cellObj=self.obj.excelCellObject",I think its worth stating this is `versionMajor` +344,"@@ -375,3 +375,14 @@ func (nc NodeController) readGenesisJSON(genesisFile string) (genesisLedger book + err = protocol.DecodeJSON(genesisText, &genesisLedger) + return + } ++ ++// SetConsensus applies a new consensus settings which would get deployed before ++// any of the nodes starts ++func (nc NodeController) SetConsensus(consensus config.ConsensusProtocols) error { ++ return config.SaveConfigurableConsensus(nc.algodDataDir, consensus) ++} ++ ++// GetConsensus rebuild the consensus version from the data directroy ++func (nc NodeController) GetConsensus() (config.ConsensusProtocols, error) { ++ return config.PreloadConfigurableConsensusProtocols(nc.algodDataDir) ++}",rebuild: say loads and merges +345,"@@ -20,7 +20,6 @@ + * External dependencies + */ + import { getDefaultOptions } from 'expect-puppeteer'; +-import { Page, ElementHandle } from 'puppeteer'; + + /** + * Jest matcher for asserting the given instance has tracking loaded or not.",Why was this removed here (also in the other file)? Shouldn't we import them so that the reference in the docs below is interpreted correctly? +346,"@@ -32,13 +32,12 @@ from databricks.koalas.series import Series + + + class PySparkTestCase(unittest.TestCase): +- + def setUp(self): + self._old_sys_path = list(sys.path) + if SparkContext._active_spark_context is not None: + SparkContext._active_spark_context.stop() + class_name = self.__class__.__name__ +- self.sc = SparkContext('local[4]', class_name) ++ self.sc = SparkContext(""local[4]"", class_name) + + def tearDown(self): + self.sc.stop()",I'd prefer to have a blank line between the class declaration and its first member. Is it possible? +347,"@@ -299,7 +299,7 @@ describe('Mongos SRV Polling', function () { + return records.map(r => `${r.name}:${r.port}`); + } + +- const MONGOS_DEFAULT_ISMASTER = Object.assign({}, mock.DEFAULT_ISMASTER_36, { ++ const MONGOS_LEGACY_HELLO = Object.assign({}, mock.HELLO, { + msg: 'isdbgrid' + }); + ",Is it really LEGACY_HELLO if we are using the most up to date HELLO? Perhaps `MONGOS_HELLO` would work here? +348,"@@ -1922,10 +1922,10 @@ detach_on_permanent_stack(bool internal, bool do_cleanup) + DEBUG_DECLARE(bool ok;) + DEBUG_DECLARE(int exit_res;) + /* synch-all flags: if we fail to suspend a thread (e.g., privilege +- * problems) ignore it. XXX Should we retry instead? ++ * problems) retry it. + */ + /* i#297: we only synch client threads after process exit event. */ +- uint flags = THREAD_SYNCH_SUSPEND_FAILURE_IGNORE | THREAD_SYNCH_SKIP_CLIENT_THREAD; ++ uint flags = THREAD_SYNCH_SUSPEND_FAILURE_RETRY | THREAD_SYNCH_SKIP_CLIENT_THREAD; + + ENTERING_DR(); + ","I am afraid this is going to cause problems on Windows where it is not uncommon to have injected threads (CTRL_SHUTDOWN, CTRL_LOGOFF, etc.) we have no privileges to suspend -- and thus retrying will just fail again, and with the new ""synchall failure is fatal and should kill the process"" approach it turns what used to work for us on Windows into process death." +349,"@@ -45,6 +45,7 @@ program + .option('-C ', 'build config (out/Debug, out/Release') + .option('--target_arch ', 'target architecture', 'x64') + .option('--mac_signing_identifier ', 'The identifier to use for signing') ++ .option('--mac_installer_signing_identifier ', 'The identifier to use for signing the installer') + .option('--mac_signing_keychain ', 'The identifier to use for signing', 'login') + .option('--debug_build ', 'keep debugging symbols') + .option('--official_build ', 'force official build settings')",think it should only be in create_dist +350,"@@ -429,9 +429,14 @@ func (c *NPLController) handleAddUpdatePod(key string, obj interface{}) error { + podPorts[port] = struct{}{} + portData := c.portTable.GetEntryByPodIPPort(podIP, int(cport.ContainerPort)) + if portData == nil { // rule does not exist +- nodePort, err = c.portTable.AddRule(podIP, port) +- if err != nil { +- return fmt.Errorf(""failed to add rule for Pod %s: %v"", key, err) ++ if int(cport.HostPort) > 0 { ++ klog.V(4).Infof(""Host Port is defined for Container %s in Pod %s, thus extra NPL port is not allocated"", container.Name, key) ++ nodePort = int(cport.HostPort) ++ } else { ++ nodePort, err = c.portTable.AddRule(podIP, port) ++ if err != nil { ++ return fmt.Errorf(""failed to add rule for Pod %s: %v"", key, err) ++ } + } + } else { + nodePort = portData.NodePort",Do you plan to support Pod spec change? Like hostPort is added/removed later after Pod creation? +351,"@@ -157,13 +157,14 @@ func (tlf *TLF) GetFileInformation(ctx context.Context, fi *dokan.FileInfo) (st + } + + // open tries to open a file. +-func (tlf *TLF) open(ctx context.Context, oc *openContext, path []string) (dokan.File, bool, error) { ++func (tlf *TLF) open(ctx context.Context, oc *openContext, path []string) ( ++ dokan.File, dokan.CreateStatus, error) { + if len(path) == 0 { + if err := oc.ReturningDirAllowed(); err != nil { +- return nil, true, err ++ return nil, 0, err + } + tlf.refcount.Increase() +- return tlf, true, nil ++ return tlf, dokan.ExistingDir, nil + } + + mode := libkbfs.ReadMode","Is this behavior correct? It used to return `true`, which should map to `dokan.ExistingDir`. Was that previously a bug?" +352,"@@ -27,7 +27,11 @@ void deleteRegion(const storage::SharedRegionRegister::ShmKey key) + + void listRegions() + { +- ++ if (!storage::SharedMonitor::exists()) ++ { ++ osrm::util::Log() << ""No shared memory regions found. Try running osrm-datastore""; ++ return; ++ } + storage::SharedMonitor monitor; + std::vector names; + const auto &shared_register = monitor.data();",What about just printing an empty list in this case? That would make the output more predictable. +353,"@@ -24,7 +24,6 @@ export default Component.extend({ + + init() { + this._super(...arguments); +- this.container = document.querySelector('.gh-editor-container')[0]; + + let mobiledoc = this.get('value') || BLANK_DOC; + let userCards = this.get('cards') || [];","I looked and couldn't find any usage of `container` in any of the editor component files (js or hbs), so I assume this was used once and didn't get removed?" +354,"@@ -256,11 +256,11 @@ function roots_request_filter($query_vars) { + add_filter('request', 'roots_request_filter'); + + /** +- * Tell WordPress to use searchform.php from the templates/ directory ++ * Tell WordPress to use searchform.php from the templates/ directory. Requires WordPress 3.6+ + */ +-function roots_get_search_form($argument) { +- if ($argument === '') { +- locate_template('/templates/searchform.php', true, false); +- } ++function roots_get_search_form($form) { ++ $form = ''; ++ locate_template('/templates/searchform.php', true, false); ++ return $form; + } + add_filter('get_search_form', 'roots_get_search_form');",I just updated a number of sites using older versions of Roots onto WP 3.6 and this little function change was required. Multiple search bars were displaying when I used the search widget in a widgetized sidebar. Updated the roots_get_search_form as seen in this change resolved it for me! +355,"@@ -19,6 +19,7 @@ use Thelia\Condition\ConditionEvaluator; + use Thelia\Condition\Implementation\MatchForTotalAmount; + use Thelia\Condition\Operators; + use Thelia\Coupon\FacadeInterface; ++use Thelia\Coupon\Type\FreeProduct; + use Thelia\Model\CartItem; + use Thelia\Model\CountryQuery; + use Thelia\Model\CurrencyQuery;",Fixes test failed in some cases +356,"@@ -23,9 +23,7 @@ module.exports = [ + 'https://balance-staging.mercury.basicattentiontoken.org/', + 'https://publishers.basicattentiontoken.org/', + 'https://publishers-staging.basicattentiontoken.org/', +- 'https://updates.bravesoftware.com/', // remove this once updates are moved to the prod environment +- 'https://ads-serve.bravesoftware.com/', // remove this once ads catalog moves to using prod +- 'https://pdfjs.robwu.nl/logpdfjs', // allowed because it gets canceled in tracking protection ++ 'https://updates.bravesoftware.com/', + 'https://publishers-distro.basicattentiontoken.org/', + 'https://publishers-staging-distro.basicattentiontoken.org/', + 'https://p3a.brave.com/',",what's the prod url for this? just curious. @amirsaber +357,"@@ -153,6 +153,12 @@ public class Constants { + // Overridable plugin load properties + public static final String AZ_PLUGIN_LOAD_OVERRIDE_PROPS = ""azkaban.plugin.load.override.props""; + ++ // Append JVM args to job commands ++ public static final String AZ_JOB_COMMAND_ARGS = ""azkaban.jvm.cmd.args""; ++ ++ // Ignore the above JVM args for jobtypes which have this true. ++ public static final String AZ_JOB_IGNORE_JVM_ARGS = ""ignore.jvm.args""; ++ + /** + * File containing param override configs + * For a directory structure, property files in Proj_Dir used to have lower precedence than A.",Can you please change this to azkaban.jobs.java.opts? +358,"@@ -66,11 +66,10 @@ function AcquisitionPieChart( { data, args, source } ) { + + let sourceMessage = ''; + if ( source ) { +- sourceMessage = sprintf( +- /* translators: %1$s: URL to Analytics Module page in Site Kit Admin, %2$s: Analytics (Service Name) */ +- __( 'Source: %2$s', 'google-site-kit' ), ++ sourceMessage = __( 'Source:', 'google-site-kit' ) + sprintf( ++ ' %2$s', + getSiteKitAdminURL( 'googlesitekit-module-analytics' ), +- _x( 'Analytics', 'Service name', 'google-site-kit' ), ++ _x( 'Analytics', 'Service name', 'google-site-kit' ) + ); + } + ","Here is another concatenation which should be updated. Even though `Source:` and the link are essentially separate, it isn't RTL friendly. This would be another good use for `createInterpolateElement` I think so that we wouldn't need to include all of the classnames in the translation string (or extract them to a placeholder). That would allow us to use the `Link` component as well, rather than using its resulting HTML as a string which will be a pain to maintain if we were to make changes to the base `Link` component." +359,"@@ -26,12 +26,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure + #endif + } + +- public static Task GetCancelledZeroTask() ++ public static Task GetCancelledZeroTask(CancellationToken cancellationToken = default(CancellationToken)) + { +- // Task.FromCanceled doesn't return Task ++#if NETSTANDARD1_3 ++ return Task.FromCanceled(cancellationToken); ++#else + var tcs = new TaskCompletionSource(); + tcs.TrySetCanceled(); + return tcs.Task; ++#endif + } + } + }",I would add an overload `GetCancelledZeroTask()` which calls `GetCancelledZeroTask(CancellationToken.None)`. This is cleaner than requiring the caller to pass `default(CancellationToken)` or `CancellationToken.None`. +360,"@@ -295,9 +295,13 @@ void BestPractices::PreCallRecordDestroyImage(VkDevice device, VkImage image, co + } + + void BestPractices::PreCallRecordDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) { +- SWAPCHAIN_NODE* chain = GetSwapchainState(swapchain); +- for (auto& image : chain->images) { +- ReleaseImageUsageState(image.image_state->image()); ++ if (VK_NULL_HANDLE != swapchain) { ++ SWAPCHAIN_NODE* chain = GetSwapchainState(swapchain); ++ for (auto& image : chain->images) { ++ if (image.image_state) { ++ ReleaseImageUsageState(image.image_state->image()); ++ } ++ } + } + ValidationStateTracker::PreCallRecordDestroySwapchainKHR(device, swapchain, pAllocator); + }","Would it be equivalent to check if `chain != nullptr` below? Not suggesting a change, just curious." +361,"@@ -1131,9 +1131,10 @@ bool nano::wallet::change_sync (nano::account const & source_a, nano::account co + + void nano::wallet::change_async (nano::account const & source_a, nano::account const & representative_a, std::function)> const & action_a, uint64_t work_a, bool generate_work_a) + { +- wallets.node.wallets.queue_wallet_action (nano::wallets::high_priority, shared_from_this (), [source_a, representative_a, action_a, work_a, generate_work_a](nano::wallet & wallet_a) { ++ wallets.node.wallets.queue_wallet_action (nano::wallets::high_priority, shared_from_this (), [this, source_a, representative_a, action_a, work_a, generate_work_a](nano::wallet & wallet_a) { + auto block (wallet_a.change_action (source_a, representative_a, work_a, generate_work_a)); + action_a (block); ++ this->wallets.queue_work_regeneration (std::chrono::steady_clock::now (), block); + }); + } + ","Should probably do `auto this_l (shared_from_this ());` and pass/use that instead of `this`. Same a few other places. IOW, replace both `shared_from_this()` and `this` with `this_l`" +362,"@@ -55,7 +55,8 @@ module.exports = iterateJsdoc( + ) { + context.report( { + data: { name: jsdocNode.name }, +- message: `The first word in a function's description should be a third-person verb (eg ""runs"" not ""run"").`, ++ message: ++ 'The first word in a function\'s description should be a third-person verb (eg ""runs"" not ""run"").', + node: jsdocNode, + } ); + }","And here. Please, use `'` for apostrophes in changed strings in this file." +363,"@@ -100,7 +100,7 @@ func (gs *GasStation) EstimateGasForAction(actPb *iotextypes.Action) (uint64, er + if err != nil { + return 0, err + } +- _, receipt, err := gs.bc.ExecuteContractRead(callerAddr, sc) ++ _, receipt, err := gs.bc.SimulateExecution(callerAddr, sc) + if err != nil { + return 0, err + }",assignments should only be cuddled with other assignments (from `wsl`) +364,"@@ -504,7 +504,15 @@ func (c *ConfigLocal) MetadataVersion() MetadataVer { + + // DataVersion implements the Config interface for ConfigLocal. + func (c *ConfigLocal) DataVersion() DataVer { +- return 1 ++ return FilesWithHolesDataVer ++} ++ ++// DefaultNewBlockDataVersion returns the default data version for new blocks. ++func DefaultNewBlockDataVersion(c Config, holes bool) DataVer { ++ if holes { ++ return FilesWithHolesDataVer ++ } ++ return FirstValidDataVer + } + + // DoBackgroundFlushes implements the Config interface for ConfigLocal.",Please move this to `block_types.go`. +365,"@@ -40,9 +40,6 @@ namespace NLog.Layouts + /// JSON attribute. + /// + [NLogConfigurationItem] +- [ThreadAgnostic] +- [ThreadSafe] +- [AppDomainFixedOutput] + public class JsonAttribute + { + /// ",So this is not needed anymore for all attributes? +366,"@@ -46,13 +46,13 @@ namespace OpenTelemetry.Extensions.Hosting.Implementation + } + } + +- [Event(1, Message = ""Failed to initialize: '{0}'. OpenTelemetry will not work."", Level = EventLevel.Error)] ++ [Event(1, Message = ""An exception occured while adding OpenTelemetry Tracing to ServiceCollection. OpenTelemetry tracing will not work. Exception: '{0}'."", Level = EventLevel.Error)] + public void FailedInitialize(string exception) + { + this.WriteEvent(1, exception); + } + +- [Event(2, Message = ""Failed to get OpenTelemetrySDK: '{0}'. OpenTelemetry will not work."", Level = EventLevel.Error)] ++ [Event(2, Message = ""An exception occured while retrieving OpenTelemetry Tracer from Service Provider. OpenTelemetry tracing will not work. Exception: '{0}'."", Level = EventLevel.Error)] + public void FailedOpenTelemetrySDK(string exception) + { + this.WriteEvent(2, exception);",Happy to get suggestion for better messaging here. Here's what I intended to convey: Something is wrong - the Exception is a hint to what might be the cause The impact of that - tracing wont work. +367,"@@ -108,6 +108,11 @@ def start_acm(port=None, asynchronous=False): + return start_moto_server('acm', port, name='ACM', asynchronous=asynchronous) + + ++def start_ses(port=None, asynchronous=False, update_listener=None): ++ port = port or config.PORT_SES ++ return start_moto_server('ses', port, name='SES', asynchronous=asynchronous, update_listener=update_listener) ++ ++ + # TODO move to es_starter.py? + def start_elasticsearch_service(port=None, asynchronous=False): + port = port or config.PORT_ES","I think we can remove this function, right? (duplicate with `ses_starter.py`)" +368,"@@ -195,6 +195,10 @@ class PandasLikeSeries(_Frame): + ""Field {} not found, possible values are {}"".format(name, "", "".join(fnames))) + return anchor_wrap(self, self._spark_getField(name)) + ++ # TODO: automate the process here ++ def alias(self, name): ++ return self.rename(name) ++ + @property + def schema(self): + if not hasattr(self, '_pandas_schema') or self._pandas_schema is None:","With this fix, I am not even sure we need to overwrite this function." +369,"@@ -311,6 +311,8 @@ class PackageEntry(object): + class Package(object): + """""" In-memory representation of a package """""" + ++ use_tqdm = os.getenv('QUILT_USE_TQDM').lower() == 'true' ++ + def __init__(self): + self._children = {} + self._meta = {'version': 'v0'}",Why not just import this from `data_transfer`? As a rule copying the same code twice is not a good idea. Also: please run `pylint` on all files in this PR. +370,"@@ -99,7 +99,7 @@ module Beaker + it ""can correctly combine arguments from different sources"" do + FakeFS.deactivate! + args = [""-h"", hosts_path, ""--debug"", ""--type"", ""git"", ""--install"", ""PUPPET/1.0,HIERA/hello""] +- expect(parser.parse_args(args)).to be === {:hosts_file=>hosts_path, :options_file=>nil, :type=>""git"", :provision=>true, :preserve_hosts=>false, :root_keys=>false, :quiet=>false, :xml=>false, :color=>true, :debug=>true, :dry_run=>false, :fail_mode=>nil, :timesync=>false, :repo_proxy=>false, :add_el_extras=>false, :consoleport=>443, :pe_dir=>""/opt/enterprise/dists"", :pe_version_file=>""LATEST"", :pe_version_file_win=>""LATEST-win"", :dot_fog=>""#{home}/.fog"", :ec2_yaml=>""config/image_templates/ec2.yaml"", :ssh=>{:config=>false, :paranoid=>false, :timeout=>300, :auth_methods=>[""publickey""], :port=>22, :forward_agent=>true, :keys=>[""#{home}/.ssh/id_rsa""], :user_known_hosts_file=>""#{home}/.ssh/known_hosts""}, :install=>[""git://github.com/puppetlabs/puppet.git#1.0"", ""git://github.com/puppetlabs/hiera.git#hello""], :HOSTS=>{:""pe-ubuntu-lucid""=>{:roles=>[""agent"", ""dashboard"", ""database"", ""master""], :vmname=>""pe-ubuntu-lucid"", :platform=>""ubuntu-10.04-i386"", :snapshot=>""clean-w-keys"", :hypervisor=>""fusion""}, :""pe-centos6""=>{:roles=>[""agent""], :vmname=>""pe-centos6"", :platform=>""el-6-i386"", :hypervisor=>""fusion"", :snapshot=>""clean-w-keys""}}, :nfs_server=>""none"", :puppet_ver=>nil, :facter_ver=>nil, :hiera_ver=>nil, :hiera_puppet_ver=>nil, :helper=>[], :load_path=>[], :tests=>[], :pre_suite=>[], :post_suite=>[], :modules=>[]} ++ expect(parser.parse_args(args)).to be === {:hosts_file=>""/Users/anode/beaker/spec/beaker/options/data/hosts.cfg"", :options_file=>nil, :type=>""git"", :provision=>true, :preserve_hosts=>false, :root_keys=>false, :quiet=>false, :xml=>false, :color=>true, :debug=>true, :dry_run=>false, :fail_mode=>nil, :timesync=>false, :repo_proxy=>false, :add_el_extras=>false, :consoleport=>443, :pe_dir=>""/opt/enterprise/dists"", :pe_version_file=>""LATEST"", :pe_version_file_win=>""LATEST-win"", :dot_fog=>""/Users/anode/.fog"", :ec2_yaml=>""config/image_templates/ec2.yaml"", :ssh=>{:config=>false, :paranoid=>false, :timeout=>300, :auth_methods=>[""publickey""], :port=>22, :forward_agent=>true, :keys=>[""/Users/anode/.ssh/id_rsa""], :user_known_hosts_file=>""/Users/anode/.ssh/known_hosts""}, :install=>[""git://github.com/puppetlabs/puppet.git#1.0"", ""git://github.com/puppetlabs/hiera.git#hello""], :HOSTS=>{:""pe-ubuntu-lucid""=>{:roles=>[""agent"", ""dashboard"", ""database"", ""master""], :vmname=>""pe-ubuntu-lucid"", :platform=>""ubuntu-10.04-i386"", :snapshot=>""clean-w-keys"", :hypervisor=>""fusion""}, :""pe-centos6""=>{:roles=>[""agent""], :vmname=>""pe-centos6"", :platform=>""el-6-i386"", :hypervisor=>""fusion"", :snapshot=>""clean-w-keys""}}, :nfs_server=>""none"", :helper=>[], :load_path=>[], :tests=>[], :pre_suite=>[], :post_suite=>[], :modules=>[]} + end + + it ""ensures that file-mode is one of fast/stop"" do",You've got an absolute path here referencing your home dir :-). +371,"@@ -526,10 +526,10 @@ public final class JavaParserMetaModel { + unaryExprMetaModel.getDeclaredPropertyMetaModels().add(unaryExprMetaModel.expressionPropertyMetaModel); + unaryExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, ""operator"", com.github.javaparser.ast.expr.UnaryExpr.Operator.class, Optional.empty(), false, false, false, false, false); + unaryExprMetaModel.getDeclaredPropertyMetaModels().add(unaryExprMetaModel.operatorPropertyMetaModel); +- unaryExprMetaModel.prefixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, ""prefix"", boolean.class, Optional.empty(), false, true, false, false, false); +- unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.prefixPropertyMetaModel); + unaryExprMetaModel.postfixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, ""postfix"", boolean.class, Optional.empty(), false, true, false, false, false); + unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.postfixPropertyMetaModel); ++ unaryExprMetaModel.prefixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, ""prefix"", boolean.class, Optional.empty(), false, true, false, false, false); ++ unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.prefixPropertyMetaModel); + variableDeclarationExprMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, ""annotations"", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false); + variableDeclarationExprMetaModel.getDeclaredPropertyMetaModels().add(variableDeclarationExprMetaModel.annotationsPropertyMetaModel); + variableDeclarationExprMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, ""modifiers"", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);",Maybe I should do some sorting so that these properties don't keep moving around... +372,"@@ -32,14 +32,6 @@ func TestCheckMountDestFalsePositive(t *testing.T) { + } + } + +-func TestCheckMountRoot(t *testing.T) { +- dest := ""/rootfs"" +- err := checkMountDestination(""/rootfs"", dest) +- if err == nil { +- t.Fatal(err) +- } +-} +- + func TestNeedsSetupDev(t *testing.T) { + config := &configs.Config{ + Mounts: []*configs.Mount{","Can we keep this test anyway, as it's part of the spec?" +373,"@@ -0,0 +1,19 @@ ++ // Code generated by protoc-gen-go. DO NOT EDIT. +381,"@@ -46,6 +46,9 @@ var ( + utils.GcloudProdWrapperLatest: ""gcloud"", + utils.GcloudLatestWrapperLatest: ""gcloud"", + } ++ // Apply this as instance metadata if the OS config agent is not ++ // supported for the platform or version being imported. ++ skipOSConfig = map[string]string{""osconfig_not_supported"": ""true""} + ) + + type ovfInstanceImportTestProperties struct {","minor: skipOSConfigMetadata, otherwise, the name sounds like a boolean" +382,"@@ -56,7 +56,9 @@ public class NSRSS20 extends Namespace { + boolean validType = false; + boolean validUrl = !TextUtils.isEmpty(url); + +- if (type == null) { ++ if(SyndTypeUtils.enclosureTypeValid(type)) { ++ validType = true; ++ } else { + type = SyndTypeUtils.getMimeTypeFromUrl(url); + } + ","~~I think lines 65-67 should be moved into this else clause after `type = ...` Else, it is a bit confusing why we check the enclose type validity a second time~~ Nevermind, will do some refactoring, myself. But thanks for ""fixing"" this!" +383,"@@ -239,3 +239,16 @@ func (client *Client) Stop() error { + + return nil + } ++ ++// GetSessions returns all sessions from history ++func (client *Client) GetSessions() (endpoints.SessionsDTO, error) { ++ response, err := client.http.Get(""sessions"", url.Values{}) ++ if err != nil { ++ return endpoints.SessionsDTO{}, err ++ } ++ defer response.Body.Close() ++ ++ var sessions endpoints.SessionsDTO ++ err = parseResponseJSON(response, &sessions) ++ return sessions, err ++}",`sessions := endpoints.SessionsDTO{}` and using only `sessions` should be simpler. +384,"@@ -5242,8 +5242,11 @@ master_signal_handler_C(byte *xsp) + + /* Ensure we didn't get the app's sigstack into our frame. On Mac, the kernel + * doesn't use the frame's uc_stack, so we limit this to Linux. ++ * The pointers may be different if a thread is on its way to exit, and the app's ++ * sigstack was already restored (i#3369). + */ +- IF_LINUX(ASSERT(dcontext == NULL || dcontext == GLOBAL_DCONTEXT || ++ IF_LINUX(ASSERT(dcontext == NULL || dcontext->is_exiting || ++ dcontext == GLOBAL_DCONTEXT || + frame->uc.uc_stack.ss_sp == + ((thread_sig_info_t *)dcontext->signal_field)->sigstack.ss_sp)); + ",These need to be in the other order to avoid crashing when dcontext == GLOBAL_DCONTEXT (==-1) +385,"@@ -24,7 +24,8 @@ namespace Http2SampleApp + factory.SetMinimumLevel(LogLevel.Trace); + factory.AddConsole(); + }) +- .UseKestrel((context, options) => ++ .UseKestrel() ++ .ConfigureKestrel((context, options) => + { + var basePort = context.Configuration.GetValue(""BASE_PORT"") ?? 5000; + ",Why not change the other samples? +386,"@@ -10,8 +10,9 @@ table.isHeader = function (cell) { + return true; + } + +- if (cell.id) { +- return !!document.querySelector('[headers~=""' + axe.utils.escapeSelector(cell.id) + '""]'); ++ if (cell.getAttribute('id')) { ++ const id = axe.utils.escapeSelector(cell.getAttribute('id')); ++ return !!document.querySelector(`[headers~=""${id}""]`); + } + + return false;","Indentation is mixed up here due to spaces/tabs, I'm guessing." +387,"@@ -738,9 +738,15 @@ static fpga_result poll_interrupt(fpga_dma_handle dma_h) { + res = FPGA_EXCEPTION; + } else { + uint64_t count = 0; +- read(pfd.fd, &count, sizeof(count)); +- debug_print(""Poll success. Return = %d, count = %d\n"",poll_res, (int)count); +- res = FPGA_OK; ++ ssize_t bytes_read = read(pfd.fd, &count, sizeof(count)); ++ if(bytes_read <= 0) { ++ fprintf( stderr, ""Error: %s\n"", ++ bytes_read < 0 ? strerror(errno) : ""zero bytes read""); ++ res = FPGA_EXCEPTION; ++ } else { ++ debug_print(""Poll success. Return = %d, count = %d\n"",poll_res, (int)count); ++ res = FPGA_OK; ++ } + } + + out:",Should we provide a little more context in the error message? Maybe throw in something about what operation was being performed? +388,"@@ -138,7 +138,10 @@ class PluginBase extends ServiceProviderBase + */ + public function registerSettings() + { +- return []; ++ $configuration = $this->getConfigurationFromYaml(); ++ if (array_key_exists('settings', $configuration)) { ++ return $configuration['settings']; ++ } + } + + /**","Project standard is spaces, not tabs. Please fix and then we can merge this." +389,"@@ -1,12 +1,14 @@ + #include ""dynamic_zone.h"" +-#include ""expedition.h"" +-#include ""expedition_state.h"" ++#include ""cliententry.h"" ++#include ""clientlist.h"" ++#include ""dynamic_zone_manager.h"" + #include ""worlddb.h"" + #include ""zonelist.h"" + #include ""zoneserver.h"" + #include ""../common/eqemu_logsys.h"" + #include ""../common/repositories/instance_list_repository.h"" + ++extern ClientList client_list; + extern ZSList zoneserver_list; + + Database& DynamicZone::GetDatabase()",@hgtw is there anything we're worried about with regards to using this cache? Do we want to do staged testing around expeditions before we merge? Curious your thoughts here +390,"@@ -226,11 +226,11 @@ public class ManifestReader extends CloseableGroup implements Filterable iterator() { +- return iterator(alwaysTrue(), fileSchema); ++ return iterator(fileSchema); + } + + // visible for use by PartialManifest +- Iterator iterator(Expression partFilter, Schema fileProjection) { ++ Iterator iterator(Schema fileProjection) { + return Iterables.transform(Iterables.filter( + entries(fileProjection), + entry -> entry.status() != ManifestEntry.Status.DELETED),",The purpose of this was to allow pushing filters into the manifest files if we ever use a format other than Parquet. I think overall this is a good change because we can add it back later. Just wanted to note why the unused argument was there. +391,"@@ -24,7 +24,15 @@ module Mongoid + # @since 1.0.0 + def evolve(object) + __evolve__(object) do |obj| +- obj ? obj.to_s : obj ++ if obj ++ if obj.is_a?(::BigDecimal) && Mongoid.map_big_decimal_to_decimal128 ++ BSON::Decimal128.new(obj) ++ elsif obj.is_a?(BSON::Decimal128) && Mongoid.map_big_decimal_to_decimal128 ++ obj ++ else ++ obj.to_s ++ end ++ end + end + end + end",I think BSON::Decimal128 should always be serialized as Decimal128 regardless of config option. +392,"@@ -1,6 +1,7 @@ + # frozen_string_literal: true + + require 'bolt/application' ++require 'bolt/plan_creator' + + require 'bolt_spec/files' + ",We should probably just move the `require 'bolt/plan_creator'` in `Bolt::CLI` to `Bolt::Application` so it will already be loaded. +393,"@@ -34,7 +34,10 @@ namespace Benchmarks + + private static IConfig GetConfig(Options options) + { +- var baseJob = Job.ShortRun; // let's use the Short Run for better first user experience ;) ++ var baseJob = Job.Default ++ .WithWarmupCount(1) // 1 warmup is enough for our purpose ++ .WithMaxTargetIterationCount(20); // we don't want to run more that 20 iterations ++ + var jobs = GetJobs(options, baseJob).ToArray(); + + var config = DefaultConfig.Instance",">20 [](start = 45, length = 2) Can we override this at runtime? Maybe it should be a command line option with default." +394,"@@ -47,7 +47,7 @@ class Service(object): + self.start_error_message = start_error_message + self.log_file = log_file + self.env = env or os.environ +- ++ + @property + def service_url(self): + """"""",can just remove it ? +395,"@@ -654,7 +654,17 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) { + return repo, UpdateRepository(repo, false) + } + +- if err = createUpdateHook(repoPath); err != nil { ++ repo, err = FinishMigrateRepository(repo, repoPath) ++ if err != nil { ++ return repo, err ++ } ++ ++ return repo, UpdateRepository(repo, false) ++} ++ ++// Finish migrating repository with things that don't need to be done for mirrors. ++func FinishMigrateRepository(repo *Repository, repoPath string) (*Repository, error) { ++ if err := createUpdateHook(repoPath); err != nil { + return repo, fmt.Errorf(""createUpdateHook: %v"", err) + } + ",Better call it `CleanUpMirrorInfo`? +396,"@@ -405,6 +405,19 @@ func (node *Node) SetupMining(ctx context.Context) error { + } + } + ++ if err := node.StorageMining.Start(ctx); err != nil { ++ fmt.Printf(""error starting storage miner: %s\n"", err) ++ } ++ ++ if err := node.StorageProtocol.StorageProvider.Start(ctx); err != nil { ++ fmt.Printf(""error starting storage provider: %s\n"", err) ++ } ++ ++ // TODO: Retrieval Market Integration ++ //if err := node.RetrievalProtocol.RetrievalProvider.Start(); err != nil { ++ // fmt.Printf(""error starting retrieval provider: %s\n"", err) ++ //} ++ + return nil + } + ",@shannonwells is there still something missing here? +397,"@@ -149,6 +149,9 @@ MESSAGE + # don't accidentally leave the seed encoded. + define_reader :seed + ++ # Time limit for stress testing, if any (default: nil). ++ add_setting :stress_test ++ + # When a block passed to pending fails (as expected), display the failure + # without reporting it as a failure (default: false). + add_setting :show_failures_in_pending_blocks",This could be more indicative of what it is... e.g... `stresstest_time_limit` +398,"@@ -279,7 +279,6 @@ bool PDPSimple::createPDPEndpoints() + delete mp_listener; + mp_listener = nullptr; + reader_payload_pool_->release_history(reader_pool_cfg, true); +- TopicPayloadPoolRegistry::release(reader_payload_pool_); + return false; + } + ",Shouldn't we do a `reader_payload_pool_.reset()` here? +399,"@@ -33,9 +33,9 @@ type Block struct { + // ElectionProof is the vrf proof giving this block's miner authoring rights + ElectionProof *crypto.ElectionProof + +- // DrandEntries contain the verifiable oracle randomness used to elect ++ // BeaconEntries contain the verifiable oracle randomness used to elect + // this block's author leader +- DrandEntries []*drand.Entry ++ BeaconEntries []*drand.Entry + + // PoStProofs are the winning post proofs + PoStProofs []PoStProof `json:""PoStProofs""`",I'd prefer the nomenclature less tightly coupled to DRAND throughout. I played with renaming the `drand` package to `beacon` but it was too much noise in this change. +400,"@@ -853,6 +853,11 @@ class DynamicMap(HoloMap): + unbounded_dims.append(str(kdim)) + return unbounded_dims + ++ @property ++ def current_key(self): ++ """"""Returns the current key value."""""" ++ return getattr(self, '_current_key', None) ++ + def _stream_parameters(self): + return util.stream_parameters( + self.streams, no_duplicates=not self.positional_stream_args",I think I would prefer you declare `self._current_key=None` in the constructor and just return `self._current_key`. That way you can prevent anyone from overwriting `current_key` without needing to use `getattr` here. +401,"@@ -22,8 +22,14 @@ const FromCSVKind = ""fromCSV"" + type FromCSVOpSpec struct { + CSV string `json:""csv""` + File string `json:""file""` ++ Mode string `json:""mode""` + } + ++const ( ++ annotationMode = ""annotations"" ++ rawMode = ""raw"" ++) ++ + func init() { + fromCSVSignature := runtime.MustLookupBuiltinType(""csv"", ""from"") + runtime.RegisterPackageValue(""csv"", ""from"", flux.MustValue(flux.FunctionValue(FromCSVKind, createFromCSVOpSpec, fromCSVSignature)))",I guess I like the name `mode` okay. I can't think of anything better. +402,"@@ -69,8 +69,12 @@ type Step struct { + testType stepImpl + } + +-// NewStep creates a Step with given name and timeout with the specified workflow ++// NewStep creates a Step with given name and timeout with the specified workflow. ++// If timeout is less or equal to zero, defaultTimeout from the workflow will be used + func NewStep(name string, w *Workflow, timeout time.Duration) *Step { ++ if timeout <= 0 { ++ return &Step{name: name, w: w, Timeout: w.DefaultTimeout} ++ } + return &Step{name: name, w: w, timeout: timeout} + } + ",I would create a new method (NewStepWithDefaultTimeout?) for this purpose because timeout<=0 looks like a hidden logic +403,"@@ -71,6 +71,7 @@ func Register(r *gin.RouterGroup, s *Service) { + // @Param experimentNamespace query string false ""The namespace of the experiment"" + // @Param uid query string false ""The UID of the experiment"" + // @Param kind query string false ""kind"" Enums(PodChaos, IoChaos, NetworkChaos, TimeChaos, KernelChaos, StressChaos) ++// @Param limit query string false ""The max length of events list"" + // @Success 200 {array} core.Event + // @Router /api/events [get] + // @Failure 500 {object} utils.APIError",Are these limit changes related? +404,"@@ -18,12 +18,12 @@ Routing and network interface handling for IPv6. + + from __future__ import absolute_import + import socket ++import scapy.consts + from scapy.config import conf + from scapy.utils6 import * + from scapy.arch import * + from scapy.pton_ntop import * + from scapy.error import warning, log_loading +-from scapy.consts import LOOPBACK_INTERFACE + import scapy.modules.six as six + + ",Don't you mean `import scapy.consts`? +405,"@@ -62,3 +62,7 @@ func (e *Executor) ensurePrimaryUpdate(ctx context.Context) model.StageStatus { + e.LogPersister.AppendSuccess(fmt.Sprintf(""Successfully applied %d primary resources"", len(manifests))) + return model.StageStatus_STAGE_SUCCESS + } ++ ++func (e *Executor) rollbackPrimary(ctx context.Context) model.StageStatus { ++ return model.StageStatus_STAGE_SUCCESS ++}",`ctx` is unused in rollbackPrimary +406,"@@ -40,7 +40,7 @@ const ( + // BufferedEventID is the id of the buffered event + BufferedEventID int64 = -123 + // EmptyEventTaskID is uninitialized id of the task id within event +- EmptyEventTaskID int64 = -1234 ++ EmptyEventTaskID int64 = 0 + // TransientEventID is the id of the transient event + TransientEventID int64 = -124 + // FirstBlobPageToken is the page token identifying the first blob for each history archival",This is not what title says. +407,"@@ -0,0 +1,19 @@ ++/** ++ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html ++ */ ++ ++package net.sourceforge.pmd.autofix; ++ ++import net.sourceforge.pmd.lang.ast.Node; ++ ++/** ++ * Classes of this interface must be used when it is desired to make one or more operations to the AST. ++ */ ++public interface RuleViolationFix { ++ ++ /** ++ * Apply one or more operations to a node. ++ * @param node the node in the AST on which to apply operations ++ */ ++ void applyFixesToNode(Node node); ++}",a fix applies several fixes? maybe this should simply be `applyToNode` +408,"@@ -25,11 +25,12 @@ import ( + metav1 ""k8s.io/apimachinery/pkg/apis/meta/v1"" + ) + ++// fakeGetClientset gets the cvr clientset + func fakeGetClientset() (clientset *clientset.Clientset, err error) { + return &client.Clientset{}, nil + } + +-func fakeListfn(cli *clientset.Clientset, namespace string, opts metav1.ListOptions) (*apis.CStorVolumeReplicaList, error) { ++func fakeListOk(cli *clientset.Clientset, namespace string, opts metav1.ListOptions) (*apis.CStorVolumeReplicaList, error) { + return &apis.CStorVolumeReplicaList{}, nil + } + ",U1000: func `fakeGetOk` is unused (from `unused`) +409,"@@ -18,6 +18,8 @@ import ( + ""errors"" + ""fmt"" + ++ ""k8s.io/client-go/util/retry"" ++ + ""github.com/hashicorp/go-multierror"" + ""golang.org/x/sync/errgroup"" + v1 ""k8s.io/api/core/v1""","Because there is a ""k8s.io/client-go/tools/cache"" below, we can sort out all the ""imports"" here." +410,"@@ -3,7 +3,9 @@ + package api + + import ( ++ ""github.com/aws/aws-sdk-go/aws"" + ""fmt"" ++ ""encoding/json"" + ""reflect"" + ""sort"" + ""strings""","Nit should be using `goimports` to format the import statements with standard libary imports first, new line, followed by non-standard library imports." +411,"@@ -118,8 +118,10 @@ func (o *deletePipelineOpts) Ask() error { + + // Execute deletes the secret and pipeline stack. + func (o *deletePipelineOpts) Execute() error { +- if err := o.deleteSecret(); err != nil { +- return err ++ if o.PipelineSecret != """" { ++ if err := o.deleteSecret(); err != nil { ++ return err ++ } + } + + if err := o.deleteStack(); err != nil {",Do we not have tests for pipeline delete +412,"@@ -146,6 +146,12 @@ class HdfsClient(hdfs_abstract_client.HdfsFileSystem): + def put(self, local_path, destination): + self.call_check(load_hadoop_cmd() + ['fs', '-put', local_path, destination]) + ++ def append(self, local_path, destination): ++ """""" ++ Requires Hadoop >= 2.3.0 ++ """""" ++ call_check(load_hadoop_cmd() + ['fs', '-appendToFile', local_path, destination]) ++ + def get(self, path, local_destination): + self.call_check(load_hadoop_cmd() + ['fs', '-get', path, local_destination]) + ",Good that you mention this constraint in the docstring :) +413,"@@ -15,8 +15,13 @@ package workflow + + import ( + ""encoding/json"" ++ ""fmt"" + ""net/http"" + ++ ctrl ""sigs.k8s.io/controller-runtime"" ++ ++ apierrors ""k8s.io/apimachinery/pkg/api/errors"" ++ + ""github.com/gin-gonic/gin"" + + ""github.com/chaos-mesh/chaos-mesh/api/v1alpha1""",remove this blank? +414,"@@ -9515,7 +9515,8 @@ FileScan::FileScan(const CorrName& tableName, + estRowsAccessed_ (0), + mdamFlag_(UNDECIDED), + skipRowsToPreventHalloween_(FALSE), +- doUseSearchKey_(TRUE) ++ doUseSearchKey_(TRUE), ++ computedNumOfActivePartiions_(-1) + { + // Set the filescan properties: + ","Partitions is misspelled 8 times in this commit, might make sense to fix the spelling for all of those." +415,"@@ -22,9 +22,11 @@ + import shlex + + from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QProcess, +- QProcessEnvironment) ++ QProcessEnvironment, QUrl) + +-from qutebrowser.utils import message, log ++from qutebrowser.utils import message, log, objreg ++ ++from qutebrowser.browser import qutescheme + + # A mapping of QProcess::ErrorCode's to human-readable strings. + ",Please remove this blank line - those are only used to group Python/third-party/qutebrowser imports. +416,"@@ -45,6 +45,8 @@ var ActionCmd = &cobra.Command{ + Args: cobra.MinimumNArgs(1), + } + ++var insecure bool ++ + func init() { + ActionCmd.AddCommand(actionHashCmd) + ActionCmd.AddCommand(actionTransferCmd)",`insecure` is a global variable (from `gochecknoglobals`) +417,"@@ -479,6 +479,11 @@ func HTTPBackend(ctx *context.Context, cfg *serviceConfig) http.HandlerFunc { + for _, route := range routes { + r.URL.Path = strings.ToLower(r.URL.Path) // blue: In case some repo name has upper case name + if m := route.reg.FindStringSubmatch(r.URL.Path); m != nil { ++ if setting.Repository.DisableHttpGit { ++ w.WriteHeader(http.StatusForbidden) ++ w.Write([]byte(""Interacting with repositories by HTTP protocol is not allowed"")) ++ return ++ } + if route.method != r.Method { + if r.Proto == ""HTTP/1.1"" { + w.WriteHeader(http.StatusMethodNotAllowed)",Same as above (HTTP in upper-case) +418,"@@ -206,4 +206,11 @@ class YouTubeProviderTest extends AbstractProviderTest + $this->assertSame(100, $properties['player_parameters']['height']); + $this->assertSame(100, $properties['player_parameters']['width']); + } ++ ++ public function testGetReferenceUrl() ++ { ++ $media = new Media(); ++ $media->setProviderReference('123456'); ++ $this->assertEquals('http://www.youtube.com/watch?v=123456', $this->getProvider()->getReferenceUrl($media)); ++ } + }",This is getting repetitive maybe you could introduce an abstract test case with a `getExpectedUrl($providerReference)` method ? +419,"@@ -0,0 +1,5 @@ ++package reflect ++ ++func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { ++ return Value{} ++}","I do not think returning `Value{}` is correct here. For example, `reflect.MakeFunc(...).Kind()` would return `reflect.Invalid` instead of `reflect.Func`. Therefore, I think this should panic instead." +420,"@@ -73,7 +73,7 @@ function setProperty(dom, name, value, oldValue, isSvg) { + else if (name[0]==='o' && name[1]==='n') { + let useCapture = name !== (name=name.replace(/Capture$/, '')); + let nameLower = name.toLowerCase(); +- name = (nameLower in dom ? nameLower : name).substring(2); ++ name = (nameLower in window ? nameLower : name).substring(2); + + if (value) { + if (!oldValue) dom.addEventListener(name, eventProxy, useCapture);",Does this work for Custom Elements? iirc we're lacking test cases for them. /cc @andrewiggins @developit +421,"@@ -224,9 +224,7 @@ func (m *ipipManager) CompleteDeferredWork() error { + for _, ip := range m.activeHostnameToIP { + members = append(members, ip) + } +- for _, ip := range m.externalNodeCIDRs { +- members = append(members, ip) +- } ++ members = append(members, m.externalNodeCIDRs...) + m.ipsetsDataplane.AddOrReplaceIPSet(m.ipSetMetadata, members) + m.ipSetInSync = true + }",Same change just above? +422,"@@ -35,7 +35,8 @@ + // Promise() being missing on some legacy browser, and a funky one + // is Promise() present but buggy on WebOS 2 + window.Promise = undefined; +- window.Promise = undefined; ++ /* eslint-disable-next-line no-restricted-globals -- Explicit check on self needed */ ++ self.Promise = undefined; + } + + if (!window.Promise) {",I suppose `apploader.js` isn't used by WebWorkers. So `self` will always be `window` here. +423,"@@ -7,13 +7,7 @@ test_name ""bolt plan run should apply manifest block on remote hosts via ssh"" do + extend Acceptance::BoltCommandHelper + + ssh_nodes = select_hosts(roles: ['ssh']) +- skip_targets = select_hosts(platform: [/debian-8/]) + targets = ""ssh_nodes"" +- if skip_targets.any? +- ssh_nodes -= skip_targets +- targets = ssh_nodes.each_with_object([]) { |node, acc| acc.push(node[:vmhostname]) }.join("","") +- end +- + skip_test('no applicable nodes to test on') if ssh_nodes.empty? + + dir = bolt.tmpdir('apply_ssh')",Since this var is no longer defined we should remove the `if skip_targets.any?` bit below. +424,"@@ -170,6 +170,12 @@ def func_arn(function_name): + return aws_stack.lambda_function_arn(function_name) + + ++def func_qualifier(function_name, qualifier=None): ++ arn = aws_stack.lambda_function_arn(function_name) ++ if ARN_TO_LAMBDA.get(arn).qualifier_exists(qualifier): ++ return '{}:{}'.format(arn, qualifier) ++ ++ + def check_batch_size_range(source_arn, batch_size=None): + batch_size_entry = BATCH_SIZE_RANGES.get(source_arn.split(':')[2].lower()) + if not batch_size_entry:",I think we should `return arn` as a fallback at the end of this function (otherwise the `['Resource']` entry below could become `None`). +425,"@@ -41,6 +41,11 @@ type NATProxy struct { + + func (np *NATProxy) consumerHandOff(consumerPort int, remoteConn *net.UDPConn) chan struct{} { + stop := make(chan struct{}) ++ if np.socketProtect == nil { ++ // shutdown pinger session since openvpn client will connect directly (without NATProxy) ++ remoteConn.Close() ++ return stop ++ } + go np.consumerProxy(consumerPort, remoteConn, stop) + return stop + }","Why session is started at all, if you need to shut it down e.g. DI should launch noopSession" +426,"@@ -184,7 +184,7 @@ type describer interface { + } + + type workspaceDeleter interface { +- DeleteAll() error ++ DeleteWorkspaceFile() error + } + + type svcManifestReader interface {",nit: can we rename the interface to `wsFileDeleter` +427,"@@ -91,10 +91,10 @@ func hashRule(r *rule) string { + // It's the struct used by reconciler. + type CompletedRule struct { + *rule +- // Source Pods of this rule, can't coexist with ToAddresses. +- FromAddresses v1beta1.GroupMemberPodSet +- // Destination Pods of this rule, can't coexist with FromAddresses. +- ToAddresses v1beta1.GroupMemberPodSet ++ // Source GroupMembers of this rule, can't coexist with ToAddresses. ++ FromAddresses v1beta1.GroupMemberSet ++ // Destination GroupMembers of this rule, can't coexist with FromAddresses. ++ ToAddresses v1beta1.GroupMemberSet + // Target Pods of this rule. + Pods v1beta1.GroupMemberPodSet + }",Why target cannot be external endpoints? +428,"@@ -127,4 +127,8 @@ public interface CollectionAdminParams { + + /** Option to follow aliases when deciding the target of a collection admin command. */ + String FOLLOW_ALIASES = ""followAliases""; ++ ++ /** Prefix for automatically created config elements. */ ++ String AUTO_PREFIX = "".auto_""; ++ + }","We use a suffix "".AUTOCREATED"" for configsets, maybe we can use the same here?" +429,"@@ -27,7 +27,7 @@ namespace Samples + { + // Enable OpenTelemetry for the source ""MyCompany.MyProduct.MyWebServer"" + // and use Console exporter +- OpenTelemetrySdk.Default.EnableOpenTelemetry( ++ OpenTelemetrySdk.EnableOpenTelemetry( + (builder) => builder.AddActivitySource(""MyCompany.MyProduct.MyWebServer"") + .UseConsoleActivityExporter(opt => opt.DisplayAsJson = options.DisplayAsJson)); + ",This one won't be disposed. Should be (something like) `using var openTelemetry = OpenTelemetrySdk.EnableOpenTelemetry(` no? +430,"@@ -37,7 +37,7 @@ from logHandler import log + import UIAUtils + from comInterfaces import UIAutomationClient as UIA + # F403: unable to detect undefined names +-from comInterfaces .UIAutomationClient import * # noqa: F403 ++from comInterfaces.UIAutomationClient import * # noqa: F403 + import textInfos + from typing import Dict + from queue import Queue",Why this is in the diff? +431,"@@ -136,6 +136,8 @@ type QuiesceDriver interface { + type CloudBackupDriver interface { + // CloudBackupCreate uploads snapshot of a volume to the cloud + CloudBackupCreate(input *api.CloudBackupCreateRequest) error ++ // CloudBackupGroupCreate creates and then uploads volumegroup snapshots ++ CloudBackupGroupCreate(input *api.CloudBackupGroupCreateRequest) error + // CloudBackupRestore downloads a cloud backup and restores it to a volume + CloudBackupRestore(input *api.CloudBackupRestoreRequest) (*api.CloudBackupRestoreResponse, error) + // CloudBackupEnumerate enumerates the backups for a given cluster/credential/volumeID",How is status determined? When the user calls CloudBackupCreate( src_volume_id ) they can then call CloudBackupStatus( src_volume_id ) Is there something similar for this new API? +432,"@@ -232,6 +232,15 @@ export function diff( + + if ((tmp = options.diffed)) tmp(newVNode); + } catch (e) { ++ // When we are hydrating and have excessDomChildren we don't know the _children this VNode ++ // should receive so it's safer to unmount them. Else on the subsequent error-boundary diff, ++ // we won't know the oldDom and insert an additional node instead of replace the prerendered one. (#2539) ++ if (isHydrating && excessDomChildren != null) { ++ for (tmp = excessDomChildren.length; tmp--; ) { ++ if (excessDomChildren[tmp] != null) removeNode(excessDomChildren[tmp]); ++ } ++ } ++ + newVNode._original = null; + options._catchError(e, newVNode, oldVNode); + }",We could pass `excessDomChildren` to `options._catchError` and only do this if an error-boundary catches the error. Not entirely sure if that's better. +433,"@@ -464,7 +464,7 @@ class CombineAssets + */ + protected function setHashOnCombinerFilters($hash) + { +- $allFilters = call_user_func_array('array_merge', $this->getFilters()); ++ $allFilters = array_merge(...array_values($this->getFilters())); + + foreach ($allFilters as $filter) { + if (method_exists($filter, 'setHash')) {",In php8 named parameters were introduced and now it is required to match called method parameter name when setting parameters by array destructing or call_user_func_array() etc. +434,"@@ -82,6 +82,9 @@ func (b3 B3) Extract(ctx context.Context, supplier propagation.HTTPSupplier) con + } else { + sc = b3.extract(supplier) + } ++ if !sc.IsValid() { ++ return ctx ++ } + return ContextWithRemoteSpanContext(ctx, sc) + } + ","If instead we had `B3.extractSingleHeader` and `B3.extract` return a bool value as a second return value, we could avoid the byte array comparison in `TraceID.IsValid`. Did you consider that alternative?" +435,"@@ -56,7 +56,7 @@ return [ + 'choose_file' => 'Datei auswählen', + 'close' => 'Schließen', + 'create' => 'Erstellen', +- 'create_and_add_another' => 'Erstellen und weiter hinzufügen', ++ 'create_and_add_another' => 'Erstellen und weitere hinzufügen', + 'create_and_continue' => 'Erstellen und weiter bearbeiten', + 'save' => 'Speichern', + 'save_and_continue' => 'Speichern und weiter bearbeiten',",I think this is more of a semantic difference than a typo - `weiter hinzufgen` is like `continue adding` whereas `weitere hinzufgen` is like `add more`. I think it makes sense to change it though +436,"@@ -227,3 +227,12 @@ class RecordsViewTest(BaseWebTest, unittest.TestCase): + MINIMALIST_RECORD, + headers=headers, + status=200) ++ ++ def test_records_can_be_created_after_deletion(self): ++ self.app.delete(self.record_url, ++ headers=self.headers, ++ status=200) ++ headers = self.headers.copy() ++ headers['If-None-Match'] = '*' ++ self.app.put_json(self.record_url, MINIMALIST_RECORD, ++ headers=headers, status=201)",nit: 200 is superfluous +437,"@@ -246,7 +246,7 @@ TEST_F(SchemaTest, metaCommunication) { + // Test unreserved keyword + { + cpp2::ExecutionResponse resp; +- std::string query = ""CREATE TAG upper(name string, EMAIL string, "" ++ std::string query = ""CREATE TAG upper(name string, email string, "" + ""age int, gender string, row_timestamp timestamp)""; + auto code = client->execute(query, resp); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);",This is testing `unreserved keyword` +438,"@@ -829,6 +829,10 @@ static const MethodMapping projectionMethodMappings[] = { + + {PROJ_WKT2_NAME_METHOD_QUADRILATERALIZED_SPHERICAL_CUBE, 0, + ""Quadrilateralized_Spherical_Cube"", ""qsc"", nullptr, paramsNatOrigin}, ++ ++ {PROJ_WKT2_NAME_METHOD_S2, 0, ++ ""S2"", ""s2"", nullptr, paramsNatOrigin}, ++ + + {PROJ_WKT2_NAME_METHOD_SPHERICAL_CROSS_TRACK_HEIGHT, 0, + ""Spherical_Cross_Track_Height"", ""sch"", nullptr, paramsSch},",paramsNatOrigin doesn't include sUVtoST. I would just remove that definition for now +439,"@@ -71,9 +71,15 @@ func makeKMD() KeyMetadata { + return emptyKeyMetadata{tlf.FakeID(0, tlf.Private), 1} + } + ++func initBlockRetrievalQueueTest(t *testing.T) *blockRetrievalQueue { ++ q := newBlockRetrievalQueue(0, 0, newTestBlockRetrievalConfig(t, nil, nil)) ++ <-q.TogglePrefetcher(false, nil) ++ return q ++} ++ + func TestBlockRetrievalQueueBasic(t *testing.T) { + t.Log(""Add a block retrieval request to the queue and retrieve it."") +- q := newBlockRetrievalQueue(0, 0, newTestBlockRetrievalConfig(t, nil, nil)) ++ q := initBlockRetrievalQueueTest(t) + require.NotNil(t, q) + defer q.Shutdown() + ","It feels like the test should be waiting for the prefetcher to shut down, but I don't have a great reason why other than that it might be confusing for debugging if there are still goroutines from old prefetchers lying. But I guess since `TogglePrefetcher(false)` doesn't actually set the prefetcher to nil, the queue shutdown method will still end up waiting for the shutdown to finish. If that sounds right, nevermind me." +440,"@@ -1,4 +1,4 @@ +-//snippet-sourcedescription:[ListAccessKeys.java demonstrates how to list access keys associated with an AWS Identity and Access Management (IAM) user.] ++//snippet-sourcedescription:[ListAccessKeys.java demonstrates how to list access keys associated with an AWS Identity and Access Management (AWS IAM) user.] + //snippet-keyword:[AWS SDK for Java v2] + //snippet-keyword:[Code Sample] + //snippet-service:[AWS IAM]",AWS Identity and Access Management (IAM) +441,"@@ -34,6 +34,7 @@ class LoadProjectsCloudsqlPipeline(base_pipeline.BasePipeline): + """"""Pipeline to load project CloudSql data into Inventory."""""" + + PROJECTS_RESOURCE_NAME = 'project_iam_policies' ++ RESOURCE_NAME = 'cloudsql' + RESOURCE_NAME_INSTANCES = 'cloudsql_instances' + RESOURCE_NAME_IPADDRESSES = 'cloudsql_ipaddresses' + RESOURCE_NAME_AUTHORIZEDNETWORKS = ( # pylint: disable=invalid-name","As a long term thing, would it make sense to move the resource names as keys under the requirements map?" +442,"@@ -57,7 +57,7 @@ function traverseForHeaders(headerType, position, tableGrid) { + * @return {Array} Array of headers associated to the table cell + */ + table.getHeaders = function(cell, tableGrid) { +- if (cell.hasAttribute('headers')) { ++ if (cell.getAttribute('headers')) { + return commons.dom.idrefs(cell, 'headers'); + } + if (!tableGrid) {","That doesn't fix the whole problem. The issue lays in this line right here, not the one above. There are two problems with this line: 1. It finds things that aren't cells in the table 2. if it doesn't find anything, it shouldn't return empty here, but continue down to look for row/ column headers." +443,"@@ -38,7 +38,9 @@ public class NoUnusedPinCheckTask extends DefaultTask { + + @Input + public final Set getResolvedArtifacts() { +- return BaselineVersions.getResolvedArtifacts(getProject()); ++ return getProject().getAllprojects().stream() ++ .flatMap(project -> BaselineVersions.getResolvedArtifacts(project).stream()) ++ .collect(Collectors.toSet()); + } + + @InputFile",I am pretty sure that this is infinite recursion as getAllProjects returns the project itself. +444,"@@ -268,6 +268,7 @@ Blockly.Categories = { + ""sound"": ""sounds"", + ""pen"": ""pen"", + ""data"": ""data"", ++ ""dataLists"": ""data-lists"", + ""event"": ""events"", + ""control"": ""control"", + ""sensing"": ""sensing"",","Something I didn't catch before I merged this PR, is the hyphenated constant a problem? E.g. should ""data-lists"" be ""data_lists""? @paulkaplan" +445,"@@ -248,3 +248,7 @@ L2socket: use the provided L2socket + + import scapy.sendrecv + scapy.sendrecv.sniff = sniff ++ ++# If wpcap.dll is not available ++if (not conf.use_winpcapy) and (not conf.use_pcap) and (not conf.use_dnet): ++ from scapy.arch.windows.disable_sendrecv import *",Can you write the test as `if not (conf.use_winpcapy or conf.use_pcap or conf.use_dnet):` +446,"@@ -23,6 +23,8 @@ class _Repository: + self.description = check.opt_str_param(description, ""description"") + + def __call__(self, fn: Callable[[], Any]) -> RepositoryDefinition: ++ from dagster.core.asset_defs import ForeignAsset ++ + check.callable_param(fn, ""fn"") + + if not self.name:",we have to include foreign assets on the repository directly because they don't belong to a job? This seems very awkward... Is this a step towards the job-less assets on the repository? Did you consider having `build_asset_job` take in a set of foreign assets instead? I suppose we would then need to subclass it to be a more special `AssetJobDefinition` that can keep track of them. +447,"@@ -14,8 +14,7 @@ TempDir::TempDir(const char* pathTemplate, bool deleteOnDestroy) + : deleteOnDestroy_(deleteOnDestroy) { + auto len = strlen(pathTemplate); + std::unique_ptr name(new char[len + 1]); +- strncpy(name.get(), pathTemplate, len); +- name.get()[len] = '\0'; ++ strcpy(name.get(), pathTemplate); + + VLOG(2) << ""Trying to create the temp directory with pattern \"""" + << name.get() << ""\"""";","`-Wstringop-truncation` is a new kind of error detector introduced in GCC 8. As for this patch, these are two false-positives though." +448,"@@ -36,7 +36,7 @@ const ( + + // ErrSharedConfigSourceCollision will be returned if a section contains both + // source_profile and credential_source +-var ErrSharedConfigSourceCollision = awserr.New(ErrCodeSharedConfig, ""only source profile or credential source can be specified, not both"", nil) ++var ErrSharedConfigSourceCollision = awserr.New(ErrCodeSharedConfig, ""only one credential type may be specified per profile: source profile, credential source, credential process, web identity token, or sso"", nil) + + // ErrSharedConfigECSContainerEnvVarEmpty will be returned if the environment + // variables are empty and Environment was set as the credential source","Can we port this error msg to v2 too? This one is better, as it explicitly states what sources are allowed." +449,"@@ -3,6 +3,7 @@ + var f = require('util').format; + var test = require('./shared').assert; + var setupDatabase = require('./shared').setupDatabase; ++const { ReadPreference } = require('../..'); + const Db = require('../../lib/db'); + const expect = require('chai').expect; + ",The convention so far has been to require directly from the defining file (in this case `../../read_preference') . I think the concern has been mostly about the potential for circular dependency cycles +450,"@@ -10,8 +10,9 @@ from ..registry import PIPELINES + @PIPELINES.register_module + class LoadImageFromFile(object): + +- def __init__(self, to_float32=False): ++ def __init__(self, to_float32=False, color_type='color'): + self.to_float32 = to_float32 ++ self.color_type = color_type + + def __call__(self, results): + if results['img_prefix'] is not None:",I suggest expanding dims here to simplify the formatting. +451,"@@ -9,7 +9,7 @@ from pyramid.paster import bootstrap + + from kinto.config import init + +-CONFIG_FILE = 'config/kinto.ini' ++CONFIG_FILE = 'kinto/config/kinto.ini' + + + def main(args=None):",Why do you need to specify the kinto prefix here? +452,"@@ -45,7 +45,7 @@ class FPN(nn.Module): + >>> self = FPN(in_channels, 11, len(in_channels)).eval() + >>> outputs = self.forward(inputs) + >>> for i in range(len(outputs)): +- ... print('outputs[{}].shape = {!r}'.format(i, outputs[i].shape)) ++ ... print(f'outputs[{i}].shape = {outputs[i].shape!r}') + outputs[0].shape = torch.Size([1, 11, 340, 340]) + outputs[1].shape = torch.Size([1, 11, 170, 170]) + outputs[2].shape = torch.Size([1, 11, 84, 84])",The `!r` is unnecessary. +453,"@@ -161,7 +161,7 @@ func (o *lazyCredsOpener) OpenBucketURL(ctx context.Context, u *url.URL) (*blob. + + isMSIEnvironment := adal.MSIAvailable(ctx, adal.CreateSender()) + +- if accountKey != """" { ++ if accountKey != """" || sasToken != """" { + o.opener, o.err = openerFromEnv(accountName, accountKey, sasToken, storageDomain, protocol) + } else if isMSIEnvironment { + o.opener, o.err = openerFromMSI(accountName, storageDomain, protocol)",I didn't see existing tests for this `OpenBucketURL`. Not sure if it's easy to do without mocking these `opener` calls. +454,"@@ -21,6 +21,8 @@ namespace AutoRest.Go.TemplateModels + // (null or empty if the model is not paged). + public string NextLink; + ++ public bool PreparerNeeded; ++ + public ModelTemplateModel(CompositeType source) + { + this.LoadFrom(source);",Should we default to `true` ? +455,"@@ -15,6 +15,7 @@ import ( + uconfig ""go.uber.org/config"" + + ""github.com/iotexproject/iotex-core/address"" ++ ""github.com/iotexproject/iotex-core/consensus/fsm"" + ""github.com/iotexproject/iotex-core/crypto"" + ""github.com/iotexproject/iotex-core/pkg/keypair"" + )",File is not `goimports`-ed (from `goimports`) +456,"@@ -54,11 +54,14 @@ const rules = [ + use: [ + { + loader: 'babel-loader', +- query: { +- presets: [ [ '@babel/env', { +- useBuiltIns: 'entry', +- corejs: 2, +- } ], '@babel/preset-react' ], ++ options: { ++ babelrc: false, ++ configFile: false, ++ cacheDirectory: true, ++ presets: [ ++ '@wordpress/default', ++ '@babel/preset-react', ++ ], + }, + }, + {","Shouldn't these options also include `@babel/preset-env`? Also I see you set `babelrc` to `false`, could we rely on our existing `.babelrc` file? Feels like some duplicate configuration otherwise." +457,"@@ -1609,7 +1609,7 @@ func (wn *WebsocketNetwork) removePeer(peer *wsPeer, reason disconnectReason) { + // first logging, then take the lock and do the actual accounting. + // definitely don't change this to do the logging while holding the lock. + localAddr, _ := wn.Address() +- wn.log.With(""event"", ""Disconnected"").With(""remote"", peer.rootURL).With(""local"", localAddr).Infof(""Peer %v disconnected"", peer.rootURL) ++ wn.log.With(""event"", ""Disconnected"").With(""remote"", peer.rootURL).With(""local"", localAddr).Infof(""Peer %v disconnected: %v"", peer.rootURL, reason) + peerAddr := peer.OriginAddress() + // we might be able to get addr out of conn, or it might be closed + if peerAddr == """" && peer.conn != nil {",Nit: We can use `%s` since `disconnectReason` is a string. +458,"@@ -17,7 +17,8 @@ X_test = df_test.drop(0, axis=1).values + + print('Start training...') + # train +-gbm = lgb.LGBMRegressor(objective='regression', ++gbm = lgb.LGBMRegressor(boosting_type='rgf', ++ objective='regression', + num_leaves=31, + learning_rate=0.05, + n_estimators=20)",I think it's better to create a new example +459,"@@ -392,7 +392,7 @@ void ResolveOperation(Action &action, const RENDER_PASS_STATE &rp_state, const V + + if (aspect_mask) { + action(aspect_string, ""resolve read"", src_at, dst_at, attachment_views[src_at], +- SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ, kDepthStencilAttachmentRasterOrder, offset, extent, ++ SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ, kAttachmentRasterOrder, offset, extent, + aspect_mask); + action(aspect_string, ""resolve write"", src_at, dst_at, attachment_views[dst_at], + SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, kAttachmentRasterOrder, offset, extent, aspect_mask);","The stages are correct, but the more forgiving `kAttachmentRasterOrder` should be used, based on a review of the spec. That should give the same effect of suppressing the false positive conflict between the DEPTH R/W and resolve. > End-of-subpass multisample resolves are treated as color attachment writes for the purposes of synchronization. This applies to resolve operations for both color and depth/stencil attachments. That is, they are considered to execute in the VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT pipeline stage and their writes are synchronized with VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. Synchronization between rendering within a subpass and any resolve operations at the end of the subpass occurs automatically, without need for explicit dependencies or pipeline barriers." +460,"@@ -64,7 +64,7 @@ class AcidBasePair(object): + #: Administration Substance Registration System Standard Operating Procedure guide. + ACID_BASE_PAIRS = ( + AcidBasePair('-OSO3H', 'OS(=O)(=O)[OH]', 'OS(=O)(=O)[O-]'), +- AcidBasePair('–SO3H', '[!O]S(=O)(=O)[OH]', '[!O]S(=O)(=O)[O-]'), ++ AcidBasePair('--SO3H', '[!O]S(=O)(=O)[OH]', '[!O]S(=O)(=O)[O-]'), + AcidBasePair('-OSO2H', 'O[SD3](=O)[OH]', 'O[SD3](=O)[O-]'), + AcidBasePair('-SO2H', '[!O][SD3](=O)[OH]', '[!O][SD3](=O)[O-]'), + AcidBasePair('-OPO3H2', 'OP(=O)([OH])[OH]', 'OP(=O)([OH])[O-]'),","To be consistent, I think it should actually just be a single `-`" +461,"@@ -6,6 +6,7 @@ import yaml + + from datetime import datetime + from listenbrainz.utils import escape, convert_to_unix_timestamp ++from flask import current_app + + def flatten_dict(d, seperator='', parent_key=''): + """"""",this seems extraneous. +462,"@@ -795,7 +795,7 @@ func (s *Suite) Define() { + By(""Sanity-check the issued Certificate"") + err = f.Helper().ValidateCertificate(f.Namespace.Name, ""testcert"", validations...) + Expect(err).NotTo(HaveOccurred()) +- }, featureset.OnlySAN) ++ }, featureset.OnlySAN, featureset.LongDomainFeatureSet) + + s.it(f, ""should allow updating an existing certificate with a new DNS Name"", func(issuerRef cmmeta.ObjectReference) { + testCertificate := &cmapi.Certificate{","Ah, I see here that 'LongDomain' is defined as something that contains a subdomain segment that is `maxLengthOfDomainSegment` long (which I think is 63 characters) - I don't think any public ACME servers/Let's Encrypt's staging environment has a restriction on this? if it does, and the 'pebble' based ACME server does not, then Pebble needs modifying to also fail in these cases as it aims to replicate the ACME RFC as closely as possible" +463,"@@ -112,12 +112,13 @@ module Travis + 'cdbs qpdf texinfo libssh2-1-dev devscripts '\ + ""#{optional_apt_pkgs}"", retry: true + +- r_filename = ""R-#{r_version}-$(lsb_release -cs).xz"" +- r_url = ""https://travis-ci.rstudio.org/#{r_filename}"" ++ r_filename = ""r-#{r_version}_1_amd64.deb"" ++ os_version = ""$(lsb_release -rs | tr -d '.')"" ++ r_url = ""https://cdn.rstudio.com/r/ubuntu-#{os_version}/pkgs/#{r_filename}"" + sh.cmd ""curl -fLo /tmp/#{r_filename} #{r_url}"", retry: true +- sh.cmd ""tar xJf /tmp/#{r_filename} -C ~"" +- sh.export 'PATH', ""${TRAVIS_HOME}/R-bin/bin:$PATH"", echo: false +- sh.export 'LD_LIBRARY_PATH', ""${TRAVIS_HOME}/R-bin/lib:$LD_LIBRARY_PATH"", echo: false ++ sh.cmd ""sudo apt-get install gdebi-core"" ++ sh.cmd ""sudo gdebi r-#{r_version}_1_amd64.deb"" ++ sh.export 'PATH', ""/opt/R/#{r_version}/bin:$PATH"", echo: false + sh.rm ""/tmp/#{r_filename}"" + + sh.cmd ""sudo mkdir -p /usr/local/lib/R/site-library $R_LIBS_USER""",I think you need `-y` here to prevent a user confirmation prompt +464,"@@ -100,6 +100,7 @@ bool dynamo_heap_initialized = false; + bool dynamo_started = false; + bool automatic_startup = false; + bool control_all_threads = false; ++bool dynamo_avx512_code_in_use = false; + #ifdef WINDOWS + bool dr_early_injected = false; + int dr_early_injected_location = INJECT_LOCATION_Invalid;","Repeating: I don't think this should be a core-wide global var. This should be isolated to arch/x86 or at least arch/, maybe inside getter/setters as mentioned above." +465,"@@ -55,8 +55,11 @@ class JMeterExecutor(ScenarioExecutor, WidgetProvider, FileLister): + """""" + MIRRORS_SOURCE = ""https://archive.apache.org/dist/jmeter/binaries/"" + JMETER_DOWNLOAD_LINK = ""https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-{version}.zip"" ++ PLUGINS_MANAGER = 'https://repo1.maven.org/maven2/kg/apc/jmeter-plugins-manager/0.8/jmeter-plugins-manager-0.8.jar' ++ CMDRUNNER = 'http://search.maven.org/remotecontent?filepath=kg/apc/cmdrunner/2.0/cmdrunner-2.0.jar' ++ PLUGINS = [""jpgc-casutg"", ""jpgc-dummy"", ""jpgc-ffw"", ""jpgc-fifo"", ""jpgc-functions"", ++ ""jpgc-json"", ""jpgc-perfmon"", ""jpgc-prmctl"", ""jpgc-tst""] + JMETER_VER = ""3.0"" +- PLUGINS_DOWNLOAD_TPL = ""http://jmeter-plugins.org/files/JMeterPlugins-{plugin}-1.4.0.zip"" + UDP_PORT_NUMBER = None + + def __init__(self):","right URL is like in cmdrunner, using search.maven .org" +466,"@@ -32,9 +32,9 @@ namespace OpenTelemetry.Exporter + #if NETSTANDARD2_1 + /// + /// Gets or sets the target to which the exporter is going to send traces or metrics. +- /// The valid syntax is described at https://github.com/grpc/grpc/blob/master/doc/naming.md. ++ /// The valid syntax is described at https://github.com/grpc/grpc/blob/master/doc/naming.md. The endpoint value should start with http or https. + /// +- public Uri Endpoint { get; set; } = new Uri(""http://localhost:4317""); ++ public string Endpoint { get; set; } = ""http://localhost:4317""; + #else + /// + /// Gets or sets the target to which the exporter is going to send traces or metrics.","The link to valid syntax is not really applicable for NET2_1, right?" +467,"@@ -16,6 +16,13 @@ + // PubSub. Use OpenTopic to construct a *pubsub.Topic, and/or OpenSubscription + // to construct a *pubsub.Subscription. + // ++// Escaping ++// ++// Go CDK supports all UTF-8 strings; some strings are escaped (during writes) ++// and unescaped (during reads) to ensure compatibility with the provider: ++// - Metadata keys: No escaping required. ++// - Metadata values: No escaping required. ++// + // As + // + // gcspubsub exposes the following types for As:","Shouldn't it be more specific, like ""gcppubsub supports all UTF-8 strings""?" +468,"@@ -59,14 +59,14 @@ public class CdcrReplicationHandlerTest extends BaseCdcrDistributedZkTest { + } + + /** +- * Test the scenario where the slave is killed from the start. The replication ++ * Test the scenario where the secondary is killed from the start. The replication + * strategy should fetch all the missing tlog files from the leader. + */ + @Test + @ShardsFixed(num = 2) + public void testFullReplication() throws Exception { +- List slaves = this.getShardToSlaveJetty(SOURCE_COLLECTION, SHARD1); +- slaves.get(0).jetty.stop(); ++ List secondaries = this.getShardToSecondaryJetty(SOURCE_COLLECTION, SHARD1); ++ secondaries.get(0).jetty.stop(); + + for (int i = 0; i < 10; i++) { + List docs = new ArrayList<>();","Everything in this class is SolrCloud-related, not legacy replication" +469,"@@ -1122,15 +1122,8 @@ drbbdup_prepare_redirect(dr_mcontext_t *mcontext, drbbdup_manager_t *manager, + { + /* Restore flags and scratch reg to their original app values. */ + if (!manager->are_flags_dead) { +- reg_t val; +- uint sahf; +- reg_t newval = mcontext->xflags; +- val = (reg_t)drbbdup_get_tls_raw_slot_val(DRBBDUP_FLAG_REG_SLOT); +- sahf = (val & 0xff00) >> 8; +- newval &= ~(EFLAGS_ARITH); +- newval |= sahf; +- if (TEST(1, val)) /* seto */ +- newval |= EFLAGS_OF; ++ reg_t val = (reg_t)drbbdup_get_tls_raw_slot_val(DRBBDUP_FLAG_REG_SLOT); ++ reg_t newval = dr_merge_arith_flags(mcontext->xflags, val); + mcontext->xflags = newval; + } + if (!manager->is_scratch_reg_dead) {",Could just assign directly and eliminate the `newval` var. +470,"@@ -27,11 +27,13 @@ import ( + const ( + inProgressLabel = ""in progress"" + issueTitleComment = ""Please edit the title of this issue with the name of the affected package, followed by a colon, followed by a short summary of the issue. Example: `blob/gcsblob: not blobby enough`."" ++ pullRequestTitleComment = ""Please edit the title of this pull request with the name of the affected package, followed by a colon, followed by a short summary of the change. Example: `blob/gcsblob: improve comments`."" + branchesInForkCloseComment = ""Please create pull requests from your own fork instead of from branches in the main repository. Also, please delete this branch."" + ) + + var ( +- issueTitleRegexp = regexp.MustCompile(""^[a-z0-9/]+: .*$"") ++ issueTitleRegexp = regexp.MustCompile(""^[a-z0-9/]+: .*$"") ++ pullRequestTitleRegexp = issueTitleRegexp + ) + + // issueData is information about an issue event.","... with the name of the affected package, or ""all"", followed by a colon,..." +471,"@@ -48,6 +48,10 @@ namespace PrepareRelease + ""src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj"", + NugetVersionReplace); + ++ SynchronizeVersion( ++ ""src/Datadog.Trace.ClrProfiler.Managed.Core/Datadog.Trace.ClrProfiler.Managed.Core.csproj"", ++ NugetVersionReplace); ++ + SynchronizeVersion( + ""src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt"", + text => FullVersionReplace(text, "".""));",We'll want to remove this one if we make the assembly version constant. +472,"@@ -51,6 +51,7 @@ class Frontend extends Generator { + $this->setup_blog_colors(); + $this->setup_form_fields_style(); + $this->setup_single_post_style(); ++ $this->setup_single_page_style(); + } + + /**",Can we have a single function here that uses the same subscribers and just changes meta based on context? +473,"@@ -513,8 +513,9 @@ hsa_executable_t load_executable(const string& file, hsa_executable_t executable + return executable; + } + +-// To force HIP to load the kernels and to setup the function +-// symbol map on program startup ++// HIP startup kernel loader logic ++// When enabled HIP_STARTUP_LOADER, HIP will load the kernels and setup ++// the function symbol map on program startup + class startup_kernel_loader { + private: + startup_kernel_loader() { functions(); }",where would ` static startup_kernel_loader skl;` be instantiated? if it's not instantiated anywhere should this be removed? +474,"@@ -0,0 +1,14 @@ ++const webkitGetAsEntryApi = require('./utils/webkitGetAsEntryApi') ++const getFilesAndDirectoriesApi = require('./utils/getFilesAndDirectoriesApi') ++const fallbackApi = require('./utils/fallbackApi') ++ ++module.exports = function getDroppedFiles (dataTransfer, callback) { ++ if (dataTransfer.items[0] && 'webkitGetAsEntry' in dataTransfer.items[0]) { ++ webkitGetAsEntryApi(dataTransfer, callback) ++ } else if ('getFilesAndDirectories' in dataTransfer) { ++ // Doesn't actually work in firefox, maybe in previous versions. webkitGetAsEntryApi() works. ++ getFilesAndDirectoriesApi(dataTransfer, callback) ++ } else { ++ fallbackApi(dataTransfer, callback) ++ } ++}","I think we should move those util functions that work with drag-drop to @uppy/utils, so they can be shared (maybe later) with drag-drop plugin? Otherwise it will continue to depend on drag-drop module." +475,"@@ -732,12 +732,6 @@ func (m *Volume) Contains(mid string) bool { + // Copy makes a deep copy of VolumeSpec + func (s *VolumeSpec) Copy() *VolumeSpec { + spec := *s +- if s.VolumeLabels != nil { +- spec.VolumeLabels = make(map[string]string) +- for k, v := range s.VolumeLabels { +- spec.VolumeLabels[k] = v +- } +- } + if s.ReplicaSet != nil { + spec.ReplicaSet = &ReplicaSet{Nodes: make([]string, len(s.ReplicaSet.Nodes))} + copy(spec.ReplicaSet.Nodes, s.ReplicaSet.Nodes)",Migrate the spec.Labels to locator.Labels ? +476,"@@ -250,7 +250,7 @@ func TestS3_EmptyBucket(t *testing.T) { + + gotErr := service.EmptyBucket(tc.inBucket) + +- if gotErr != nil { ++ if tc.wantErr != nil { + require.EqualError(t, gotErr, tc.wantErr.Error()) + } + })",The test case already existed but it never tested properly because of the conditional in the test. +477,"@@ -68,11 +68,9 @@ public class PartitionField implements Serializable { + } + + PartitionField that = (PartitionField) other; +- return ( +- sourceId == that.sourceId && ++ return sourceId == that.sourceId && + name.equals(that.name) && +- transform.equals(that.transform) +- ); ++ transform.equals(that.transform); + } + + @Override","I'm okay with this, but I don't see a lot of benefit to removing unnecessary parens. If extra parens make something more readable (like this) or clarify order of operations even when matching the default, I would say we should keep them." +478,"@@ -138,7 +138,7 @@ public class IndexSchema { + + protected List fieldsWithDefaultValue = new ArrayList<>(); + protected Collection requiredFields = new HashSet<>(); +- protected volatile DynamicField[] dynamicFields; ++ protected DynamicField[] dynamicFields = new DynamicField[] {}; + public DynamicField[] getDynamicFields() { return dynamicFields; } + + protected Map dynamicFieldCache = new ConcurrentHashMap<>();",@sarowe why was this volatile? It's fishy to see this as the only volatile field. +479,"@@ -0,0 +1,13 @@ ++package org.apache.servicecomb.serviceregistry.task.event; ++ ++/** ++ * 一句话功能简述 ++ * 功能详细描述 ++ * @author m00416667 ++ * @version [版本号, ] ++ * @see [相关类/方法] ++ * @since [产品/模块版本] ++ * Package Name:org.apache.servicecomb.serviceregistry.task.event ++ */ ++public class InstanceRegistryFailedEvent { ++}",template is not correct? +480,"@@ -0,0 +1,4 @@ ++from mmdet.utils import Registry ++ ++ASSIGNERS = Registry('assigner') ++SAMPLERS = Registry('sampler')",Rename the registies to `BBOX_ASSIGNERS` and `BBOX_SAMPLERS` to avoid ambiguity. There is also a registry for dataset sampler. +481,"@@ -89,9 +89,7 @@ module Beaker + describe ""provisioning and cleanup"" do + + before :each do +- vagrant.should_receive( :make_vfile ).with( @hosts ).once +- +- vagrant.should_receive( :vagrant_cmd ).with( ""destroy --force"" ).once ++ FakeFS.activate! + vagrant.should_receive( :vagrant_cmd ).with( ""up"" ).once + @hosts.each do |host| + host_prev_name = host['user']","This is no longer stubbed on every test. Perhaps it should be, and should be unstubbed in the single case that it matters." +482,"@@ -188,6 +188,11 @@ module BoltServer + [200, GC.stat.to_json] + end + ++ get '/admin/status' do ++ stats = Puma.stats ++ [200, stats.is_a?(Hash) ? stats.to_json : stats] ++ end ++ + get '/500_error' do + raise 'Unexpected error' + end",This seems much simpler! I'm not sure I follow what you mean by the threading part... Also tests are not liking this constant. Might need a require or to fully qualify this. +483,"@@ -5902,6 +5902,7 @@ os_forge_exception(app_pc target_pc, dr_exception_type_t type) + switch (type) { + case ILLEGAL_INSTRUCTION_EXCEPTION: sig = SIGILL; break; + case UNREADABLE_MEMORY_EXECUTION_EXCEPTION: sig = SIGSEGV; break; ++ case SINGLE_STEP_EXCEPTION: ASSERT_NOT_IMPLEMENTED(false); /* cf i#2144 */ + case IN_PAGE_ERROR_EXCEPTION: /* fall-through: Windows only */ + default: ASSERT_NOT_REACHED(); sig = SIGSEGV; break; + }","Convention is ""FIXME: i#2144"" or ""XXX: i#2144""" +484,"@@ -0,0 +1,7 @@ ++namespace Datadog.Trace.ClrProfiler.Interfaces ++{ ++ internal interface IHasHttpMethod ++ { ++ string GetHttpMethod(); ++ } ++}",This should probably be a property instead of a method. +485,"@@ -159,10 +159,12 @@ spec: + status: + phase: Init + versionDetails: +- current: {{ .CAST.version }} ++ status: ++ current: {{ .CAST.version }} ++ dependentsUpgraded: true ++ state: RECONCILED + desired: {{ .CAST.version }} + autoUpgrade: false +- dependentsUpgraded: true + --- + apiVersion: openebs.io/v1alpha1 + kind: RunTask","do we need to consider setting the `state` as well? If so, lot of changes might be required, like, setting to 'Reconciling' in upgrade code, setting to 'error' or 'reconciled' in volumeReconciler functions." +486,"@@ -3,7 +3,11 @@ module Blacklight::Solr + extend ActiveSupport::Concern + + included do +- self.default_processor_chain = [:default_solr_parameters, :add_query_to_solr, :add_facet_fq_to_solr, :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr, :add_sorting_to_solr, :add_group_config_to_solr ] ++ self.default_processor_chain = [ ++ :default_solr_parameters, :add_query_to_solr, :add_facet_fq_to_solr, ++ :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr, ++ :add_sorting_to_solr, :add_group_config_to_solr, :add_facet_paging_to_solr ++ ] + end + + ####",Line is too long. [82/80] +487,"@@ -1,4 +1,5 @@ +-// Copyright (c) Microsoft. All rights reserved. ++// Copyright (c) Microsoft Corporation. All rights reserved. ++// Licensed under the MIT license. See LICENSE file in the project root for full license information. + namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.Parallel + { + using System;",Add blank line below license header. +488,"@@ -110,9 +110,17 @@ public abstract class BaseMetastoreCatalog implements Catalog { + throw new NoSuchTableException(""No such table: "" + identifier); + } + +- String baseLocation = location != null ? location : defaultWarehouseLocation(identifier); + Map tableProperties = properties != null ? properties : Maps.newHashMap(); +- TableMetadata metadata = TableMetadata.newTableMetadata(schema, spec, baseLocation, tableProperties); ++ ++ TableMetadata metadata; ++ if (ops.current() != null) { ++ String baseLocation = location != null ? location : ops.current().location(); ++ metadata = ops.current().buildReplacement(schema, spec, baseLocation, tableProperties); ++ } else { ++ String baseLocation = location != null ? location : defaultWarehouseLocation(identifier); ++ metadata = TableMetadata.newTableMetadata(schema, spec, baseLocation, tableProperties); ++ } ++ + if (orCreate) { + return Transactions.createOrReplaceTableTransaction(identifier.toString(), ops, metadata); + } else {","I'm not clear on whether this really should be the right behavior. Basically we're saying that a replace table will keep the existing location (as opposed to using defaults). I suspect we don't have create or replace with location semantics, but this is making some assumptions that a replacement is somehow the same as the old. If we were to go with id based pathing convention, this wouldn't work. I don't think this is an issue at this point, but it might make sense to push this down to the location provider." +489,"@@ -37,8 +37,10 @@ import ( + executionpb ""go.temporal.io/temporal-proto/execution"" + tasklistpb ""go.temporal.io/temporal-proto/tasklist"" + ++ executionproto ""github.com/temporalio/temporal/.gen/proto/execution"" + ""github.com/temporalio/temporal/.gen/proto/persistenceblobs"" + replicationgenpb ""github.com/temporalio/temporal/.gen/proto/replication"" ++ + ""github.com/temporalio/temporal/common"" + ""github.com/temporalio/temporal/common/checksum"" + ""github.com/temporalio/temporal/common/persistence/serialization""",Just run a global replacement for all `executionproto`. +490,"@@ -111,7 +111,7 @@ class WebDriver(object): + + def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', + desired_capabilities=None, browser_profile=None, proxy=None, +- keep_alive=False, file_detector=None): ++ keep_alive=False, file_detector=None, options=None): + """""" + Create a new driver that will issue commands using the wire protocol. + ",@AutomatedTester @davehunt thoughts on a new keyword argument? +491,"@@ -49,6 +49,9 @@ fpga_result opae_ioctl(int fd, int request, ...) + case EINVAL: + res = FPGA_INVALID_PARAM; + break; ++ case ENOTSUP: ++ res = FPGA_NOT_SUPPORTED; ++ break; + default: + // other errors could be + // EBADF - fd is bad file descriptor",Should line 47 be OPAE_ERR? +492,"@@ -104,6 +104,8 @@ import ( + ""gocloud.dev/pubsub/driver"" + ) + ++var zeroTime time.Time ++ + // Message contains data to be published. + type Message struct { + // Body contains the content of the message.","Not necessary, just write `time.Time{}`" +493,"@@ -499,6 +499,11 @@ def data(readonly=False): + SettingValue(typ.Bool(), 'true'), + ""Whether to show favicons in the tab bar.""), + ++ ('tabbar-size', ++ SettingValue(typ.Int(minval=8), '12'), ++ ""The height of the tabbar in pixels."" ++ ""This also controls the size of the favicons.""), ++ + ('width', + SettingValue(typ.PercOrInt(minperc=0, maxperc=100, minint=1), + '20%'),","As these two strings simply get concatenated for the docs, there's a space missing after the dot here." +494,"@@ -29,6 +29,7 @@ namespace Datadog.Trace.ClrProfiler.CallTarget + { + if (IntegrationOptions.IsIntegrationEnabled) + { ++ IntegrationOptions.RecordTelemetry(); + return BeginMethodHandler.Invoke(instance); + } + ",What about integrations where we don't plug ourselved on OnMethodBegin? +495,"@@ -102,7 +102,7 @@ class presence_of_all_elements_located(object): + def __call__(self, driver): + return _find_elements(driver, self.locator) + +-class visibility_of_all_elements_located(object): ++class visibility_of_any_elements_located(object): + """""" An expectation for checking that there is at least one element visible + on a web page. + locator is used to find the element",shouldn't **call** return a boolean? +496,"@@ -18,12 +18,15 @@ import com.google.api.codegen.SnippetSetRunner; + import com.google.api.codegen.viewmodel.FileHeaderView; + import com.google.api.codegen.viewmodel.ViewModel; + import com.google.api.codegen.viewmodel.testing.MockServiceImplView.Builder; ++import com.google.api.tools.framework.model.Interface; + import com.google.auto.value.AutoValue; + import java.util.List; + + @AutoValue + public abstract class GapicSurfaceTestClassView implements ViewModel { + ++ public abstract Interface service(); ++ + public abstract FileHeaderView fileHeader(); + + public abstract String name();",ViewModel classes should not expose any classes from framework.model. +497,"@@ -135,9 +135,6 @@ def test_single_required_string_field_config_type(): + assert _validate(_single_required_string_config_dict(), {'string_field': 'value'}) == { + 'string_field': 'value' + } +- assert _validate(_single_required_string_config_dict(), {'string_field': None}) == { +- 'string_field': None +- } + + with pytest.raises(DagsterEvaluateConfigValueError): + _validate(_single_required_string_config_dict(), {})",how would you feel about keeping these tests to be more explicit and having them `assert not _validate...`? or is your view that that is too duplicative of the tests in `test_evaluator.py`? +498,"@@ -21,10 +21,11 @@ test_name ""bolt plan run should apply manifest block on remote hosts via winrm"" + scp_to(bolt, File.join(fixtures, 'example_apply'), ""#{dir}/modules/example_apply"") + end + +- bolt_command = ""bolt plan run example_apply filepath=#{filepath} nodes=winrm_nodes"" ++ bolt_command = ""bolt plan run example_apply filepath=#{filepath}"" + flags = { + '--modulepath' => modulepath(File.join(dir, 'modules')), +- '--format' => 'json' ++ '--format' => 'json', ++ '-t' => ""winrm_nodes"" + } + + teardown do","Why do we use the `winrm_nodes` variable here and not the string `""winrm_nodes""` as we were using before?" +499,"@@ -1,4 +1,4 @@ +-/* Copyright (c) 2018 vesoft inc. All rights reserved. ++/* Copyright (c) 2019 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory.",why update Copyright ? +500,"@@ -7469,7 +7469,14 @@ RelExpr *Scan::bindNode(BindWA *bindWA) + bindWA->setErrStatus(); + return NULL; + } +- ++ if (naTable->hasLobColumn() && isSampleScan()) ++ { ++ *CmpCommon::diags() << DgSqlCode(-4322) ++ << DgTableName( ++ naTable->getTableName().getQualifiedNameAsAnsiString()); ++ bindWA->setErrStatus(); ++ return NULL; ++ } + // restricted partitions for HBase table + if (naTable->isHbaseTable() && + (naTable->isPartitionNameSpecified() ||",Does this mean we cannot update statistics with sampling on a table with LOB columns? +501,"@@ -47,7 +47,18 @@ namespace NLog.LayoutRenderers.Wrappers + [ThreadAgnostic] + public sealed class CachedLayoutRendererWrapper : WrapperLayoutRendererBase + { +- private string cachedValue; ++ /// ++ /// A value indicating when the cache is cleared. ++ /// ++ public enum ClearCacheOption ++ { ++ /// Never clear the cache. ++ Never = 0, ++ /// Clear the cache whenever the is initialized. ++ OnInitialize = 1 ++ } ++ ++ private string cachedValue = null; + + /// + /// Initializes a new instance of the class.","Look good, but I think a `[flags]` enum would be more future proof? Although i'm not sure if a flags-enum is working from the XML config. What do you think?" +502,"@@ -1577,6 +1577,16 @@ + require: '^uiGrid', + link: function($scope, $elm, $attrs, uiGridCtrl) { + var self = uiGridCtrl.grid; ++ $scope.treeButtonClass = function(row) { ++ if ( ( self.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) { ++ if (row.treeNode.state === 'expanded' ) { ++ return 'ui-grid-icon-minus-squared'; ++ } ++ if (row.treeNode.state === 'collapsed' ) { ++ return 'ui-grid-icon-plus-squared'; ++ } ++ } ++ }; + $scope.treeButtonClick = function(row, evt) { + evt.stopPropagation(); + uiGridTreeBaseService.toggleRowTreeState(self, row, evt);","Since I believe state will never be anything other than 'expanded' or collapse, you can rewrite this as follows: `return row.treeNode.state === 'expanded' ? 'ui-grid-icon-minus-squared' : 'ui-grid-icon-plus-squared'; `" +503,"@@ -32,10 +32,6 @@ import org.apache.solr.common.SolrException; + * Solr endpoints for SolrCloud collections, and then use the + * {@link LBHttp2SolrClient} to issue requests. + * +- * This class assumes the id field for your documents is called +- * 'id' - if this is not the case, you must set the right name +- * with {@link #setIdField(String)}. +- * + * @lucene.experimental + * @since solr 8.0 + */","the latter part can go but isn't the first part of this still sound -- that we assume ""id""?" +504,"@@ -27,14 +27,12 @@ var formatter = this; + string = function(value) { + if (value != null) { + value = value.replace(/\\/g, '\\\\'); +- value = value.replace(/\""/g, '\\""'); ++ value = value.replace(/\'/g, '\\\''); + value = value.replace(/\r/g, '\\r'); + value = value.replace(/\n/g, '\\n'); +- value = value.replace(/@/g, '\\@'); +- value = value.replace(/\$/g, '\\$'); +- return '""' + value + '""'; ++ return '\'' + value + '\''; + } else { +- return '""""'; ++ return '\'\''; + } + } + ",Why is the escaping of @ and $ removed? +505,"@@ -0,0 +1,7 @@ ++namespace Datadog.Trace.ClrProfiler.Interfaces ++{ ++ internal interface IHasHttpUrl ++ { ++ string GetRawUrl(); ++ } ++}",Nit: `Http` is redundant in this interface's name. +506,"@@ -82,6 +82,19 @@ func NewCluster(ctx context.Context, cfg *ClusterConfig, creds credentials.Trans + if err != nil { + return nil, nil, err + } ++ ++ exists, err := store.Exists(cfg.SynchronizableEntitiesPrefix) ++ if err != nil { ++ return nil, nil, fmt.Errorf(""failed to check if SynchronizableEntitiesPrefix exists: %s"", err) ++ } ++ ++ if !exists { ++ err = store.Put(cfg.SynchronizableEntitiesPrefix, []byte{}, nil) ++ if err != nil { ++ return nil, nil, err ++ } ++ } ++ + endpoints, err := parseEndpoints(cfg) + if err != nil { + return nil, nil, err","what if I set SynchronizableEntitiesPrefix to ""a/b/c/d"" in config?" +507,"@@ -83,9 +83,13 @@ func (opts *InitAppOpts) Validate() error { + } + } + if opts.DockerfilePath != """" { +- if _, err := listDockerfiles(opts.fs, opts.DockerfilePath); err != nil { ++ isDir, err := afero.IsDir(opts.fs, opts.DockerfilePath) ++ if err != nil { + return err + } ++ if isDir { ++ return fmt.Errorf(""dockerfile path expected, got %s"", opts.DockerfilePath) ++ } + } + if opts.ProjectName() == """" { + return errNoProjectInWorkspace","nit: This error message doesn't mention that the path is a directory, maybe ""Dockerfile path is a directory:%s, please provide path to file.""" +508,"@@ -26,6 +26,7 @@ + # Copyright (c) 2020 Anthony + # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com> + # Copyright (c) 2021 Peter Kolbus ++# Copyright (c) 2021 Daniel van Noord <13665637+DanielNoord@users.noreply.github.com> + + + # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html","This is done automatically, you can skip it next time ;)" +509,"@@ -128,6 +128,14 @@ class WebKitElement(webelem.AbstractWebElement): + value = javascript.string_escape(value) + self._elem.evaluateJavaScript(""this.value='{}'"".format(value)) + ++ def dispatch_event(self, event): ++ self._check_vanished() ++ if self._tab.is_deleted(): ++ raise webelem.OrphanedError(""Tab containing element vanished"") ++ log.webelem.debug(""Firing event on {!r} via javascript."".format(self)) ++ self._elem.evaluateJavaScript(""this.dispatchEvent(new Event('{}'))"" ++ .format(event)) ++ + def caret_position(self): + """"""Get the text caret position for the current element."""""" + self._check_vanished()","This is needed in `set_value` because of `:open-editor` (you could open an editor, close the tab, then close the editor). I don't think it makes any sense to have it here?" +510,"@@ -53,6 +53,10 @@ type agentConfig struct { + + ConfigPath string + Umask string `hcl:""umask""` ++ ++ ProfilingEnabled string `hcl:""profiling_enabled""` ++ ProfilingPort string `hcl:""profiling_port""` ++ ProfilingFreq string `hcl:""profiling_freq""` + } + + type RunCLI struct {","Perhaps we can assume that profiling is enabled if ProfilingPort is set? And/or configure a default port and frequency, so we don't have to set three config vars every time?" +511,"@@ -22,6 +22,7 @@ module Beaker + #HACK HACK HACK - add checks here to ensure that we have box + box_url + #generate the VagrantFile + v_file = ""Vagrant.configure(\""2\"") do |c|\n"" ++ v_file << "" c.ssh.forward_agent = true\n"" unless options['forward_ssh_agent'].nil? + hosts.each do |host| + host['ip'] ||= randip #use the existing ip, otherwise default to a random ip + v_file << "" c.vm.define '#{host.name}' do |v|\n""",This nil check won't correctly handle the case where forward_ssh_agent is set to false - it won't be nil but it should still not be set. +512,"@@ -521,7 +521,7 @@ func TestVoteTrackerFiltersDuplicateVoteOnce(t *testing.T) { + inputVotes[i] = helper.MakeValidVoteAcceptedVal(t, i, next, Val1) + expectedOutputs[i] = thresholdEvent{T: none} + case i == Num: +- inputVotes[i] = voteFilterRequestEvent{RawVote: inputVotes[Num-1].(voteAcceptedEvent).Vote.R} ++ inputVotes[i] = voteFilterRequestEvent{RawVote: inputVotes[Num-1].(voteAcceptedEvent).Vote.R, Proto: protocol.ConsensusCurrentVersion} + expectedOutputs[i] = filteredStepEvent{T: voteFilteredStep} + } + }",We could avoid passing proto since threshold isn't needed. +513,"@@ -1040,7 +1040,10 @@ func (di *Dependencies) AllowURLAccess(servers ...string) error { + return err + } + +- if config.GetBool(config.FlagKeepConnectedOnFail) { ++ // Doesn't work as expected because some services share IP address with ++ // each other and with location oracle which is supposed to be routed ++ // through VPN tunnel. ++ if false && config.GetBool(config.FlagKeepConnectedOnFail) { + if err := router.AllowURLAccess(servers...); err != nil { + return err + }","This route excluding needed for reconnect only when one connection is lost and we trying to establish another. I was thinking to make 2 separate flags for killswitch and reconnect enabling. This way we can keep killswitch working, but we don't need these routes excluded." +514,"@@ -124,8 +124,8 @@ RocksEngine::RocksEngine(GraphSpaceID spaceId, + } + CHECK(status.ok()) << status.ToString(); + db_.reset(db); +- partsNum_ = allParts().size(); + extractorLen_ = sizeof(PartitionID) + vIdLen; ++ partsNum_ = allParts().size(); + LOG(INFO) << ""open rocksdb on "" << path; + + backup();",why can this modification avoid crash? +515,"@@ -1,8 +1,7 @@ + module RedirectIfDisabled + def redirect_if_disabled +- account = current_user +- return unless account && account.access.disabled? +- request.env[:clearance].sign_out +- redirect_to disabled_account_url(account) ++ return unless @account && @account.access.disabled? ++ request.env[:clearance].sign_out if @account.id == current_user.id ++ redirect_to disabled_account_url(@account) + end + end",This looks good -- signing out the user if the current user is disabled +516,"@@ -47,13 +47,13 @@ class Selection { + */ + this.selectedByCorner = false; + /** +- * The collection of the selection layer levels where the whole row was selected using the row header. ++ * The collection of the selection layer levels where the whole row was selected using the row header or the corner header. + * + * @type {Set.} + */ + this.selectedByRowHeader = new Set(); + /** +- * The collection of the selection layer levels where the whole column was selected using the column header. ++ * The collection of the selection layer levels where the whole column was selected using the column header or the corner header. + * + * @type {Set.} + */",The line exceeds 120 characters. +517,"@@ -62,6 +62,11 @@ func renderAppDescribe(desc map[string]interface{}) (string, error) { + ddevapp.RenderAppRow(appTable, desc) + output = fmt.Sprint(appTable) + ++ output = output + ""\n\nSite Information\n-----------------\n"" ++ siteInfo := uitable.New() ++ siteInfo.AddRow(""PHP version:"", desc[""php_version""]) ++ output = output + fmt.Sprint(siteInfo) ++ + // Only show extended status for running sites. + if desc[""status""] == ddevapp.SiteRunning { + output = output + ""\n\nMySQL Credentials\n-----------------\n""","Let's go ahead and change ""Site"" to ""Project"", since that's the path we've chosen. One less thing to alter in the other issue." +518,"@@ -89,7 +89,6 @@ Prints out information about filecoin process and its environment. + sw.Printf(""\nEnvironment\n"") + sw.Printf(""FilAPI: \t%s\n"", info.Environment.FilAPI) + sw.Printf(""FilPath:\t%s\n"", info.Environment.FilPath) +- sw.Printf(""GoPath: \t%s\n"", info.Environment.GoPath) + + // Print Config Info + sw.Printf(""\nConfig\n"")","I am for this change iff we are sure the information is no longer helpful. I think this could still be valuable for certain scenarios, wbu?" +519,"@@ -296,11 +296,16 @@ public class ImageRampupManagerImpl implements ImageRampupManager { + if (null == flow) { + log.info(""Flow object is null, so continue""); + final ImageRampup firstImageRampup = imageRampupList.get(0); ++ ++ // Find the imageVersion in the Rampup list with maximum rampup percentage. ++ final ImageRampup maxImageRampup = imageRampupList.stream() ++ .max(Comparator.comparing(ImageRampup::getRampupPercentage)) ++ .orElseGet(() -> firstImageRampup); + imageTypeRampupVersionMap.put(imageTypeName, +- this.fetchImageVersion(imageTypeName, firstImageRampup.getImageVersion()) ++ this.fetchImageVersion(imageTypeName, maxImageRampup.getImageVersion()) + .orElseThrow(() -> new ImageMgmtException( + String.format(""Unable to fetch version %s from image "" + ""versions table."", +- firstImageRampup.getImageVersion())))); ++ maxImageRampup.getImageVersion())))); + continue; + } + int prevRampupPercentage = 0;",I thought we decided on using the latest active version and not the one which is max ramped up. +520,"@@ -461,10 +461,13 @@ https://aws.amazon.com/premiumsupport/knowledge-center/ecs-pull-container-api-er + if err != nil { + if err == selector.ErrSubnetsNotFound { + log.Errorf(`No existing public subnets were found in VPC %s. You can either: +-- Create new public subnets and then import them. +-- Use the default Copilot environment configuration.`, o.importVPC.ID) ++- %s to interrupt, create new public subnets, then rerun %s and import them. ++- %s to interrupt, then rerun %s and use the default Copilot environment configuration. ++- Proceed without public subnets, knowing that deploying a load-balanced web service in this environment will fail because Load Balancers require at least two public subnets in different Availability Zones. ++`, o.importVPC.ID, color.HighlightUserInput(""ctrl-c""), color.HighlightCode(""copilot env init""), color.HighlightUserInput(""ctrl-c""), color.HighlightCode(""copilot env init"")) ++ } else { ++ return fmt.Errorf(""select public subnets: %w"", err) + } +- return fmt.Errorf(""select public subnets: %w"", err) + } + o.importVPC.PublicSubnetIDs = publicSubnets + }",can we update this to a `log.Warningf`? +521,"@@ -105,7 +105,11 @@ def connect_container_to_network(container, network): + + + def disconnect_container_from_network(container, network): +- subprocess.check_call([""docker"", ""network"", ""disconnect"", network, container]) ++ # subprocess.run instead of subprocess.check_call so we don't fail when ++ # trying to disconnect a container from a network that it's not connected to ++ subprocess.run( # pylint: disable=subprocess-run-check ++ [""docker"", ""network"", ""disconnect"", network, container] ++ ) + + + def hostnames(network):",can we get something emitted in the logs on non-zero exits to trace back to for problems like this failing on the first invocation? +522,"@@ -20,9 +20,10 @@ namespace storage { + TEST(DeleteVertexTest, SimpleTest) { + fs::TempDir rootPath(""/tmp/DeleteVertexTest.XXXXXX""); + std::unique_ptr kv(TestUtils::initKV(rootPath.path())); ++ auto schemaMan = TestUtils::mockSchemaMan(); + // Add vertices + { +- auto* processor = AddVerticesProcessor::instance(kv.get(), nullptr, nullptr); ++ auto* processor = AddVerticesProcessor::instance(kv.get(), schemaMan.get(), nullptr); + cpp2::AddVerticesRequest req; + req.space_id = 0; + req.overwritable = false;",Do we need `schema manager` at here ? +523,"@@ -0,0 +1,19 @@ ++package parser ++ ++//go:generate cargo build --release ++ ++// #cgo LDFLAGS: -L${SRCDIR}/target/release -ldl -Wl,-Bstatic -lflux_parser -Wl,-Bdynamic ++// #include ++// void flux_parse_json(const char*); ++import ""C"" ++ ++import ( ++ ""unsafe"" ++) ++ ++func Parse(input string) { ++ cstr := C.CString(input) ++ defer C.free(unsafe.Pointer(cstr)) ++ ++ C.flux_parse_json(cstr) ++}","This won't work because of the permissions on the directory when this is included as a library. But, we may be able to do this. The key would be wrapping this command with either a script or a go binary that ensures the current directory is writable. If the current directory is not writable, it would attempt to make it writable so that we could write out the produced binary. But I'm not sure if that will influence the hash that gets produced for `go.sum` since I am not sure how that is calculated. Alternatively, we can choose a place in `/usr/local` or choose a location that is writable in the go cache and use that. I'll give that a try since it might be needed for the ARM builds if we choose to only include `x86_64` precompiled binaries in the module." +524,"@@ -153,6 +153,8 @@ func (r *REPL) executeLine(t string) (values.Value, error) { + return nil, err + } + ++ r.scope.SetReturn(nil) ++ + if _, err := r.interpreter.Eval(semPkg, r.scope, flux.StdLib()); err != nil { + return nil, err + }","Correct me if I'm wrong, but is this necessary? Why not just use the value returned by `interpreter.Eval` and not mess with the scope? `interpreter.Eval` will return any produced side effects. This means TableObjects as well as any value resulting from any expression statements." +525,"@@ -162,12 +162,14 @@ func makeStatefulSetService(p *monitoringv1.Alertmanager, config Config) *v1.Ser + p.Spec.PortName = defaultPortName + } + ++ labels := config.Labels.Merge(p.Spec.ServiceMetadata.Labels) ++ labels[""operated-alertmanager""] = ""true"" ++ + svc := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ +- Name: governingServiceName, +- Labels: config.Labels.Merge(map[string]string{ +- ""operated-alertmanager"": ""true"", +- }), ++ Name: governingServiceName, ++ Labels: labels, ++ Annotations: p.Spec.ServiceMetadata.Annotations, + OwnerReferences: []metav1.OwnerReference{ + metav1.OwnerReference{ + Name: p.GetName(),","This service is global per namespace, not per Alertmanager/Prometheus/ThanosRuler instance. So this approach won't work. But maybe I missing out something, can you describe your use case here?" +526,"@@ -32,6 +32,7 @@ type AttestedNode struct { + ExpiresAt time.Time `gorm:""index""` + NewSerialNumber string + NewExpiresAt *time.Time ++ CanReattest bool `gorm:""default:false""` + + Selectors []*NodeSelector + }","Do we need this default? Since we aren't using a sql.NullBool or *bool, an unset column will be interpreted as `false` already... We don't set a default on our other bool fields (e.g. entry admin and downstream columns)." +527,"@@ -39,6 +39,18 @@ module ExportsHelper + ""#{prefix} #{attribution.join(', ')}"" + end + ++ def download_plan_page_title(plan, phase, hash) ++ # If there is more than one phase show the plan title and phase title ++ return hash[:phases].many? ? ""#{plan.title} - #{phase[:title]}"" : plan.title ++ end ++ ++ def display_section?(customization, section, show_custom_sections) ++ display = !customization ++ display ||= customization && !section[:modifiable] ++ display ||= customization && section[:modifiable] && show_custom_sections ++ return display ++ end ++ + private + + def get_margin_value_for_side(side)",thanks for moving these over. makes more sense for them to be in the exports_helper +528,"@@ -29,8 +29,9 @@ from qutebrowser.utils import message + from qutebrowser.config import config + from qutebrowser.keyinput import keyparser + from qutebrowser.utils import usertypes, log, objreg, utils ++from qutebrowser.config.parsers import keyconf + +- ++ + STARTCHARS = "":/?"" + LastPress = usertypes.enum('LastPress', ['none', 'filtertext', 'keystring']) + ",That import now isn't needed anymore +529,"@@ -237,6 +237,8 @@ class WebDriver(RemoteWebDriver): + Returns identifier of installed addon. This identifier can later + be used to uninstall addon. + ++ :param path: Full path to the addon that will be installed. ++ + :Usage: + driver.install_addon('firebug.xpi') + """"""",Can you update the `Usage` to be an absolute path as well? Something like `/path/to/firebug.xpi` +530,"@@ -2,17 +2,13 @@ + // The .NET Foundation licenses this file to you under the MS-PL license. + // See the LICENSE file in the project root for more information. + +- +-using MvvmCross.Plugins; +- + namespace MvvmCross.Plugin.Accelerometer.Platform.Uap + { +- public class Plugin +- : IMvxPlugin ++ public class Plugin : IMvxPlugin + { + public void Load() + { +- Mvx.RegisterSingleton(new MvxWindowsCommonAccelerometer()); ++ Mvx.RegisterSingleton(new MvxWindowsAccelerometer()); + } + } + }",This class is missing the `MvxPlugin` attribute +531,"@@ -596,6 +596,8 @@ def initialize(): + if mainFrame: + raise RuntimeError(""GUI already initialized"") + mainFrame = MainFrame() ++ wxLang = core.getWxLang(languageHandler.getLanguage()) ++ mainFrame.SetLayoutDirection(wxLang.LayoutDirection) + wx.GetApp().SetTopWindow(mainFrame) + # In wxPython >= 4.1, + # wx.CallAfter no longer executes callbacks while NVDA's main thread is within apopup menu or message box.",What if `wxLang` is returned `None` from `getWxLang` +532,"@@ -546,9 +546,9 @@ ResultCode NebulaStore::ingest(GraphSpaceID spaceId) { + auto files = nebula::fs::FileUtils::listAllFilesInDir(path.c_str(), true, ""*.sst""); + for (auto file : files) { + LOG(INFO) << ""Ingesting extra file: "" << file; +- auto code = engine->ingest(std::vector({file})); +- if (code != ResultCode::SUCCEEDED) { +- return code; ++ auto ret_code = engine->ingest(std::vector({file})); ++ if (ResultCode::SUCCEEDED != ret_code) { ++ return ret_code; + } + } + }",Please don't do changing like this unless it _**really**_ cares. BTW. Please look around to infer our naming conventions. +533,"@@ -35,13 +35,13 @@ public class BaseSuite { + public static ExternalResource testEnvironment = new ExternalResource() { + @Override + protected void before() { +- log.info(""Preparing test environment""); ++ log.finest(""Preparing test environment""); + GlobalTestEnvironment.get(SeleniumTestEnvironment.class); + System.setProperty(""webdriver.remote.shorten_log_messages"", ""true""); + } + @Override + protected void after() { +- log.info(""Cleaning test environment""); ++ log.finest(""Cleaning test environment""); + TestEnvironment environment = GlobalTestEnvironment.get(); + if (environment != null) { + environment.stop();",This is in test code: understanding what we're doing is important in this context. +534,"@@ -76,8 +76,8 @@ public class CommandLineUtils { + * @param isMainOptionCondition the conditions to test dependent options against. If all + * conditions are true, dependent options will be checked. + * @param dependentOptionsNames a list of option names that can't be used if condition is met. +- * Example: if --min-gas-price is in the list and condition is that either --miner-enabled or +- * --goquorum-compatibility-enabled should not be false, we log a warning. ++ * Example: if --min-gas-price is in the list and condition is that --miner-enabled should not ++ * be false, we log a warning. + */ + public static void checkMultiOptionDependencies( + final Logger logger,",prob should still have an example that has multiple option names even if you have to make it up. Or maybe we don't need this method? +535,"@@ -246,9 +246,9 @@ class PlansController < ApplicationController + file_name = @plan.title.gsub(/ /, ""_"") + + respond_to do |format| +- format.html +- format.csv { send_data @exported_plan.as_csv(@sections, @unanswered_question, @question_headings), filename: ""#{file_name}.csv"" } +- format.text { send_data @exported_plan.as_txt(@sections, @unanswered_question, @question_headings, @show_details), filename: ""#{file_name}.txt"" } ++ format.html { render layout: false } ++ format.csv { send_data @plan.as_csv(@show_sections_questions), filename: ""#{file_name}.csv"" } ++ format.text { send_data render_to_string(partial: 'shared/export/plan_txt'), filename: ""#{file_name}.txt"" } + format.docx { render docx: 'export', filename: ""#{file_name}.docx"" } + format.pdf do + render pdf: file_name,","I believe respond_to whitelists the formats passed to the block so if we don't want to display html, we can just remove the line format.html..." +536,"@@ -21,7 +21,7 @@ var LocalDevStopCmd = &cobra.Command{ + err = app.Stop() + if err != nil { + log.Println(err) +- util.Failed(""Failed to stop containers for %s. Run `ddev list` to ensure your site exists."", app.ContainerName()) ++ util.Failed(""Failed to stop containers for %s. Run `ddev list` to ensure your site exists. error="", app.ContainerName(), err) + } + + util.Success(""Application has been stopped."")","stylistic nitpick: I _feel_ like we've largely shown errors like this as ""error: "" vs. ""error="". IMO colon/space reads better." +537,"@@ -18,11 +18,16 @@ + */ + + #include ++ ++#include ++ + #include + #include +-#include +-#include ++ ++#include ++#include + #include ++#include + + #include + ",We could put this implementation in `RTPSWriter::create_change_pool` and avoid an extra function. +538,"@@ -25,6 +25,7 @@ + package persistencetests + + import ( ++ ""fmt"" + ""time"" + + ""github.com/pborman/uuid""",should this file ends with _test.go? +539,"@@ -382,7 +382,7 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools): + + if conf.checkIPsrc and conf.checkIPaddr and not in6_ismaddr(sd): + sd = inet_pton(socket.AF_INET6, sd) +- ss = inet_pton(socket.AF_INET6, self.src) ++ ss = inet_pton(socket.AF_INET6, ss) + return strxor(sd, ss) + struct.pack(""B"", nh) + self.payload.hashret() # noqa: E501 + else: + return struct.pack(""B"", nh) + self.payload.hashret()",It's because of this change. `ss` was unused and it made sense in the program. However I haven't read the IPv6 RFC so I'm unsure of what it does +540,"@@ -483,6 +483,7 @@ class DataManager { + */ + addChildAtIndex(parent, index, element) { + let childElement = element; ++ let flattenIndex; + + if (!childElement) { + childElement = this.mockNode();","""Flatten"" is a verb, so I'd probably go with `flattenedIndex` as a variable name here." +541,"@@ -1,5 +1,19 @@ + const chalk = require('chalk') + ++const valuesToMask = [] ++/** ++ * Adds a list of strings that should be masked by the logger. ++ * This function can only be called once through out the life of the server. ++ * @param {Array} maskables a list of strings to be masked ++ */ ++exports.addMaskables = (maskables) => { ++ maskables.forEach((i) => { ++ valuesToMask.push(i) ++ }) ++ ++ Object.freeze(valuesToMask) ++} ++ + /** + * INFO level log + * @param {string} msg the message to log","If it can only be called once, perhaps a more appropriate name is something like `setMaskables`? `addX` sounds like you can add many `X`es by calling it many times" +542,"@@ -38,7 +38,7 @@ func downloadAndExtractConfigPackage(channel string, targetDir string) (err erro + } + + func downloadConfigPackage(channelName string, targetDir string) (packageFile string, err error) { +- s3, err := s3.MakeS3SessionForDownload() ++ s3, err := s3.MakePublicS3SessionForDownload() + if err != nil { + return + }",Nodecfg should be downloading from a private bucket -- these shouldn't be for public consumption. In general these should be generic and expect environment to provide appropriate credentials and bucket. +543,"@@ -0,0 +1,17 @@ ++# MicrosoftEdge.py ++#A part of NonVisual Desktop Access (NVDA) ++#This file is covered by the GNU General Public License. ++#See the file COPYING for more details. ++#Copyright (C) 2018 NV Access Limited, Joseph Lee ++ ++""""""appModule for Microsoft Edge main process"""""" ++ ++import appModuleHandler ++import ui ++ ++class AppModule(appModuleHandler.AppModule): ++ ++ def event_UIA_notification(self, obj, nextHandler, displayString=None, **kwargs): ++ # #8423: even though content process is focused, notifications are fired by main Edge process. ++ # The base object will simply ignore this, so notifications must be announced here and no more. ++ ui.message(displayString)",Could you please end the file with an empty line? +544,"@@ -76,7 +76,7 @@ public class ProtocolHandshake { + + if (result.isPresent()) { + Result toReturn = result.get(); +- LOG.info(String.format(""Detected dialect: %s"", toReturn.dialect)); ++ LOG.finest(String.format(""Detected dialect: %s"", toReturn.dialect)); + return toReturn; + } + }",This is an incorrect change. The dialect spoken is an important part of the handshake and should be communicated to users. +545,"@@ -89,7 +89,9 @@ func (v *Var) UnmarshalJSON(b []byte) error { + // Workflow is a single Daisy workflow workflow. + type Workflow struct { + // Populated on New() construction. +- Cancel chan struct{} `json:""-""` ++ Cancel chan struct{} `json:""-""` ++ isCanceled bool ++ isCanceledMx sync.Mutex + + // Workflow template fields. + // Workflow name.",Can this be non-exported to avoid direct use? It would be a breaking change but using previous package version would work. +546,"@@ -145,7 +145,11 @@ func (w *watcher) ErrorAs(err error, i interface{}) bool { + return w.bucket.ErrorAs(err, i) + } + +-// IsNotExist implements driver.IsNotExist. +-func (*watcher) IsNotExist(err error) bool { +- return gcerrors.Code(err) == gcerrors.NotFound ++// ErrorCode implements driver.ErrorCode. ++func (*watcher) ErrorCode(err error) gcerrors.ErrorCode { ++ // err might have come from blob, in which case use its code. ++ if c := gcerrors.Code(err); c != gcerrors.Unknown { ++ return c ++ } ++ return gcerrors.Unknown + }","Nit: this is just `return gcerrors.Code(err)`, isn't it?" +547,"@@ -189,12 +189,7 @@ func (smc *Client) ProposeDeal(ctx context.Context, miner address.Address, data + // create payment information + totalCost := price.MulBigInt(big.NewInt(int64(pieceSize * duration))) + if totalCost.GreaterThan(types.ZeroAttoFIL) { +- // The payment setup requires that the payment is mined into a block, currently we +- // will wait for at most 5 blocks to be mined before giving up +- ctxPaymentSetup, cancel := context.WithTimeout(ctx, 5*smc.api.BlockTime()) +- defer cancel() +- +- cpResp, err := smc.api.CreatePayments(ctxPaymentSetup, porcelain.CreatePaymentsParams{ ++ cpResp, err := smc.api.CreatePayments(ctx, porcelain.CreatePaymentsParams{ + From: fromAddress, + To: minerOwner, + Value: totalCost,","I don't know where this came from, but it's not a good idea. This is actually timing out after 5 rounds, not 5 blocks. 5 consecutive null blocks won't be that uncommon. Also when testing with a short block time, this is a very short duration that can contribute to flaky tests." +548,"@@ -47,7 +47,8 @@ def loadState(): + global state + statePath=os.path.join(globalVars.appArgs.configPath,stateFilename) + try: +- state = cPickle.load(file(statePath, ""r"")) ++ with open(statePath, ""r"") as f: ++ state = cPickle.load(f) + if ""disabledAddons"" not in state: + state[""disabledAddons""] = set() + if ""pendingDisableSet"" not in state:","In Python 3 when pickling or unpickling objects, the file needs to be opened as binary so that no text encoding/decoding takes place. So for any open calls around pickle loads or dumps, the mode for reading must be rb and the mode for writing must be wb." +549,"@@ -2068,7 +2068,7 @@ const processRequest = (params) => { + } + else { + if (params.qstring.event && params.qstring.event.startsWith('[CLY]_group_')) { +- validateRead(params, 'core', countlyApi.data.fetch.fetchMergedEventGroups, params.qstring.method); ++ validateRead(params, 'core', countlyApi.data.fetch.fetchMergedEventGroups); + } + else { + params.truncateEventValuesList = true;",did you remove **params.qstring.method** intentionally? if so why? +550,"@@ -90,6 +90,12 @@ public class TableProperties { + public static final String ORC_VECTORIZATION_ENABLED = ""read.orc.vectorization.enabled""; + public static final boolean ORC_VECTORIZATION_ENABLED_DEFAULT = false; + ++ public static final String LOCALITY_ENABLED = ""read.locality.enabled""; ++ public static final String LOCALITY_ENABLED_DEFAULT = null; ++ ++ public static final String LOCALITY_TASK_INITIALIZE_THREADS = ""read.locality.task.initialize.threads""; ++ public static final int LOCALITY_TASK_INITIALIZE_THREADS_DEFAULT = 1; ++ + public static final String OBJECT_STORE_ENABLED = ""write.object-storage.enabled""; + public static final boolean OBJECT_STORE_ENABLED_DEFAULT = false; + ",What is the current default? Is that inconsistent across uses and that's why this is null? +551,"@@ -477,6 +477,7 @@ func (cf CloudFormation) getLastDeployedAppConfig(appConfig *stack.AppStackConfi + if err != nil { + return nil, fmt.Errorf(""parse previous deployed stackset %w"", err) + } ++ previouslyDeployedConfig.App = appConfig.Name + return previouslyDeployedConfig, nil + } + ",Why did we make this change? How come it wasn't an issue before +552,"@@ -4342,14 +4342,11 @@ TEST_F(VkLayerTest, InvalidDescriptorSet) { + // ObjectTracker should catch this. + // Create a valid cmd buffer + // call vk::CmdBindDescriptorSets w/ false Descriptor Set ++ ASSERT_NO_FATAL_FAILURE(Init()); + + uint64_t fake_set_handle = 0xbaad6001; + VkDescriptorSet bad_set = reinterpret_cast(fake_set_handle); + +- m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, ""VUID-vkCmdBindDescriptorSets-pDescriptorSets-parameter""); +- +- ASSERT_NO_FATAL_FAILURE(Init()); +- + VkDescriptorSetLayoutBinding layout_binding = {}; + layout_binding.binding = 0; + layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;",Can you tighten scope by moving to of these variables? i.e. Move to ~4372? +553,"@@ -90,7 +90,7 @@ public class RDATAFileReader extends TabularDataFileReader { + // RServe static variables + private static String RSERVE_HOST = System.getProperty(""dataverse.rserve.host""); + private static String RSERVE_USER = System.getProperty(""dataverse.rserve.user""); +- private static String RSERVE_PASSWORD = System.getProperty(""dataverse.rserve.pwrd""); ++ private static String RSERVE_PASSWORD = System.getProperty(""dataverse.rserve.password""); + private static int RSERVE_PORT; + + // TODO: ",Nice to see this `dataverse.rserve.password` fix rolled in. +554,"@@ -273,7 +273,7 @@ int parse_args(int argc, char *argv[]) + break; + endptr = NULL; + config.target.bus = (int) strtoul(tmp_optarg, &endptr, 0); +- if (endptr != tmp_optarg + strlen(tmp_optarg)) { ++ if (endptr != tmp_optarg + strnlen_s(tmp_optarg, sizeof(tmp_optarg))) { + fprintf(stderr, ""invalid bus: %s\n"", tmp_optarg); + return -1; + }","How about the following faster alternative that doesn't need `strlen()` at all: if (*tmp_optarg == '\0' || *endptr != '\0') { fprintf(...) ... This would treat the bus argument as invalid if it's either empty (`tmp_optarg` points to '\0') or invalid (`endptr` points to something other that a '\0'). Actually, the existing code would accept an empty argument and set the bus to `0`, so if (*endptr != '\0') { fprintf(...) ... would be enough. The check for an empty argument doesn't hurt, though." +555,"@@ -7,6 +7,7 @@ class FeedbackMailer < ApplicationMailer + to: self.class.support_email, + subject: 'Feedback submission', + from: from, ++ cc: from, + body: message + ) + end","I could be missing something here, but the `from` and `cc` are the same. On the test email sent to gatewaycommunicator, these values are different." +556,"@@ -32,13 +32,12 @@ describe('useEffect', () => { + return null; + } + +- render(, scratch); +- render(, scratch); +- +- expect(cleanupFunction).to.be.not.called; +- expect(callback).to.be.calledOnce; ++ act(() => { ++ render(, scratch); ++ render(, scratch); ++ }); + +- render(, scratch); ++ act(() => render(, scratch)); + + expect(cleanupFunction).to.be.calledOnce; + expect(callback).to.be.calledTwice;",I'm honestly scared because act is now a hard requirement for useEffect which it wasn't before... This could break some tests :( +557,"@@ -632,8 +632,13 @@ void nano::active_transactions::update_difficulty (std::shared_ptr + { + node.logger.try_log (boost::str (boost::format (""Block %1% was updated from difficulty %2% to %3%"") % block_a->hash ().to_string () % nano::to_string_hex (existing_election->difficulty) % nano::to_string_hex (difficulty))); + } +- roots.get ().modify (existing_election, [difficulty](nano::conflict_info & info_a) { ++ roots.get ().modify (existing_election, [election = existing_election->election, &block_a, difficulty](nano::conflict_info & info_a) { + info_a.difficulty = difficulty; ++ election->blocks[block_a->hash ()] = block_a; ++ if (election->status.winner->hash () == block_a->hash ()) ++ { ++ election->status.winner = block_a; ++ } + }); + adjust_difficulty (block_a->hash ()); + }","Could use election from `info_a.election`, or is this deliberate?" +558,"@@ -95,6 +95,15 @@ class EasyAdminExtension extends AbstractTypeExtension + { + return LegacyFormHelper::getType('form'); + } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public static function getExtendedTypes() ++ { ++ // needed to avoid a deprecation when using Symfony 4.2 ++ return [LegacyFormHelper::getType('form')]; ++ } + } + + class_alias('EasyCorp\Bundle\EasyAdminBundle\Form\Extension\EasyAdminExtension', 'JavierEguiluz\Bundle\EasyAdminBundle\Form\Extension\EasyAdminExtension', false);",looks like this should be `return array(LegacyFormHelper::getType('form'));` +559,"@@ -52,6 +52,8 @@ var Server = function(requestHandler) { + * with the server host when it has fully started. + */ + this.start = function(opt_port) { ++ assert(typeof opt_port !== 'function', ++ ""start invoked with function, not port (mocha callback)?""); + var port = opt_port || portprober.findFreePort('localhost'); + return promise.when(port, function(port) { + return promise.checkedNodeCall(",Maybe it would simpler to ignore opt_port if type !== 'number'? +560,"@@ -223,10 +223,9 @@ Blockly.ScratchBlocks.VerticalExtensions.SCRATCH_EXTENSION = function() { + Blockly.ScratchBlocks.VerticalExtensions.registerAll = function() { + var categoryNames = + ['control', 'data', 'data_lists', 'sounds', 'motion', 'looks', 'event', +- 'sensing', 'pen', 'operators', 'more']; ++ 'sensing', 'pen', 'operators', 'more']; + // Register functions for all category colours. +- for (var i = 0; i < categoryNames.length; i++) { +- name = categoryNames[i]; ++ for (var i = 0, name; name = categoryNames[i]; i++) { + Blockly.Extensions.register('colours_' + name, + Blockly.ScratchBlocks.VerticalExtensions.colourHelper(name)); + }",Where was `name` being declared before? +561,"@@ -74,6 +74,18 @@ func (t testHelper) UnavailableDeployment() *appsv1.Deployment { + return d + } + ++func (t testHelper) UnknownDeployment() *appsv1.Deployment { ++ d := &appsv1.Deployment{} ++ d.Name = ""unknown"" ++ d.Status.Conditions = []appsv1.DeploymentCondition{ ++ { ++ Type: appsv1.DeploymentAvailable, ++ Status: ""Unknown"", ++ }, ++ } ++ return d ++} ++ + func (t testHelper) ReadyBrokerCellStatus() *BrokerCellStatus { + bs := &BrokerCellStatus{} + bs.PropagateIngressAvailability(t.AvailableEndpoints())",nit: use `corev1.ConditionUnknown` +562,"@@ -997,7 +997,10 @@ Mongoose.prototype.isValidObjectId = function(v) { + v = v.toString(); + } + +- if (typeof v === 'string' && (v.length === 12 || v.length === 24)) { ++ if (typeof v === 'string' && v.length === 12) { ++ return true; ++ } ++ if (typeof v === 'string' && v.length === 24 && /^[a-f0-9]*$/.test(v)) { + return true; + } + ","You also need to add a similar check on line 992, there's another place where we check `length === 24`" +563,"@@ -105,9 +105,14 @@ public class BftBlockCreatorFactory { + public Bytes createExtraData(final int round, final BlockHeader parentHeader) { + final BftContext bftContext = protocolContext.getConsensusState(BftContext.class); + final ValidatorProvider validatorProvider = bftContext.getValidatorProvider(); +- checkState(validatorProvider.getVoteProvider().isPresent(), ""Bft requires a vote provider""); ++ checkState( ++ validatorProvider.getVoteProviderAfterBlock(parentHeader).isPresent(), ++ ""Bft requires a vote provider""); + final Optional proposal = +- validatorProvider.getVoteProvider().get().getVoteAfterBlock(parentHeader, localAddress); ++ validatorProvider ++ .getVoteProviderAfterBlock(parentHeader) ++ .get() ++ .getVoteAfterBlock(parentHeader, localAddress); + + final List
validators = + new ArrayList<>(validatorProvider.getValidatorsAfterBlock(parentHeader));",nit: can extract the voteProvider as a local variable +564,"@@ -1190,14 +1190,8 @@ public class QueryEqualityTest extends SolrTestCaseJ4 { + assertFuncEquals(""gte(foo_i,2)"", ""gte(foo_i,2)""); + assertFuncEquals(""eq(foo_i,2)"", ""eq(foo_i,2)""); + +- boolean equals = false; +- try { +- assertFuncEquals(""eq(foo_i,2)"", ""lt(foo_i,2)""); +- equals = true; +- } catch (AssertionError e) { +- //expected +- } +- assertFalse(equals); ++ expectThrows(AssertionError.class, ""expected error, functions are not equal"", ++ () -> assertFuncEquals(""eq(foo_i,2)"", ""lt(foo_i,2)"")); + } + + public void testChildField() throws Exception {","[0] Not suggesting you change it here, but....kindof weird that there's just not an `assertFuncNotEquals`" +565,"@@ -61,3 +61,19 @@ func (bc *Blockchain) GetAccountantFee(accountantAddress common.Address) (uint16 + + return res.Value, err + } ++ ++// IsRegistered checks wether the given identity is registered or not ++func (bc *Blockchain) IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) { ++ caller, err := bindings.NewRegistryCaller(registryAddress, bc.client) ++ if err != nil { ++ return false, errors.Wrap(err, ""could not create registry caller"") ++ } ++ ++ ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout) ++ defer cancel() ++ ++ res, err := caller.IsRegistered(&bind.CallOpts{ ++ Context: ctx, ++ }, addressToCheck) ++ return res, errors.Wrap(err, ""could not check registration status"") ++}",why are we passing 'registryAddress' here? We probably should construct it together with bc. Registry is not something that change? +566,"@@ -2,7 +2,7 @@ import { pathOr, curry, merge } from 'ramda'; + + /** + * Flattens a property path so that its fields are spread out into the provided object. +- * ++ * It's like {@link RA.spreadPath|spreadPath}, but preserves object under property path + * + * @func flattenPath + * @memberOf RA",`.` at the end of the sentence +567,"@@ -284,12 +284,16 @@ func (s *Service) checkAndAddPeers(ctx context.Context, peers pb.Peers) { + ctx, cancel := context.WithTimeout(ctx, pingTimeout) + defer cancel() + ++ start := time.Now() ++ + // check if the underlay is usable by doing a raw ping using libp2p + if _, err = s.streamer.Ping(ctx, multiUnderlay); err != nil { ++ s.metrics.PingTime.Observe(float64(time.Since(start).Milliseconds())) + s.metrics.UnreachablePeers.Inc() + s.logger.Debugf(""hive: peer %s: underlay %s not reachable"", hex.EncodeToString(newPeer.Overlay), multiUnderlay) + return + } ++ s.metrics.PingTime.Observe(float64(time.Since(start).Milliseconds())) + + bzzAddress := bzz.Address{ + Overlay: swarm.NewAddress(newPeer.Overlay),",wouldn't it be useful to split this into an error metric for the timing? +568,"@@ -47,4 +47,8 @@ class TestFakerName < Test::Unit::TestCase + assert @tester.initials.match(/[A-Z]{3}/) + assert @tester.initials(2).match(/[A-Z]{2}/) + end ++ ++ def test_fictional_character_name ++ assert @tester.fictional_character_name.match(/\w+/) ++ end + end","Not sure if this is good enough. Each generator will have it's own unit test anyway. Ideally, I think I'd want to test that each generator in the yml is actually a valid generator..." +569,"@@ -1293,6 +1293,8 @@ func newTestCFSM( + MintNewSecretBlock(gomock.Any(), gomock.Any(), gomock.Any()).Return(secretBlkToMint, nil).AnyTimes() + blockchain.EXPECT(). + Nonce(gomock.Any()).Return(uint64(0), nil).AnyTimes() ++ blockchain.EXPECT(). ++ MintNewBlockWithActionIterator(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(blkToMint, nil).AnyTimes() + if mockChain == nil { + candidates := make([]*state.Candidate, 0) + for _, delegate := range delegates {",line is 138 characters +570,"@@ -75,8 +75,9 @@ type Params struct { + TraceOpts []ocsql.TraceOption + } + +-// Open opens a Cloud SQL database. +-func Open(ctx context.Context, certSource proxy.CertSource, params *Params) (*sql.DB, error) { ++// Open opens a Cloud SQL database. The second return value is a Wire cleanup ++// function that calls Close on the returned database. ++func Open(ctx context.Context, certSource proxy.CertSource, params *Params) (*sql.DB, func(), error) { + // TODO(light): Avoid global registry once https://github.com/go-sql-driver/mysql/issues/771 is fixed. + dialerCounter.mu.Lock() + dialerNum := dialerCounter.n",Nit: I would leave `Wire` out of the description; if you use this without wire you can still use it. +571,"@@ -14,10 +14,14 @@ + */ + package com.google.api.codegen.transformer.ruby; + ++import com.google.api.codegen.config.MethodConfig; + import com.google.api.codegen.transformer.ApiMethodParamTransformer; + import com.google.api.codegen.transformer.MethodTransformerContext; ++import com.google.api.codegen.transformer.SurfaceNamer; + import com.google.api.codegen.viewmodel.DynamicLangDefaultableParamView; + import com.google.api.codegen.viewmodel.ParamDocView; ++import com.google.api.codegen.viewmodel.SimpleParamDocView; ++import com.google.api.tools.framework.model.Field; + import com.google.common.collect.ImmutableList; + import java.util.List; + ",Nit: each field can be on a separate line to make it visually easier to read. +572,"@@ -336,6 +336,7 @@ def get_analysis_statistics(inputs, limits): + statistics_files.append(compilation_db) + elif inp_f in ['compiler_includes.json', + 'compiler_target.json', ++ 'compiler_info.json', + 'metadata.json']: + analyzer_file = os.path.join(input_path, inp_f) + statistics_files.append(analyzer_file)",Do we still have these files? Shouldn't we remove these? +573,"@@ -22,6 +22,11 @@ import ( + ""github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"" + ) + ++ const ( ++ // Error reason generated when duration or renewBefore is invalid ++ ErrorDurationInvalid = ""ErrDurationInvalid"" ++) ++ + type Interface interface { + // Setup initialises the issuer. This may include registering accounts with + // a service, creating a CA and storing it somewhere, or verifying","A lot of things to do with constants seemed to move since the original commit, so I stuck this here, Is there a better place for it?" +574,"@@ -171,7 +171,9 @@ var ( + RepeatDecayStep: 1, + }, + Dispatcher: Dispatcher{ +- EventChanSize: 10000, ++ ActionChanSize: 1000, ++ BlockChanSize: 1000, ++ BlockSyncChanSize: 10, + }, + API: API{ + UseRDS: false,","is 10 too small compared to 1000? consider sync chan is unicast only (vs block chan is broadcast + unicast), i would say use 200~400 for BlockSyncChanSize my concern is that this would potentially slowdown sync speed of full-node" +575,"@@ -297,7 +297,7 @@ module Bolt + errors.each do |error| + @logger.warn(error.details['original_error']) + end +- plans ++ plans.reject { |plan| get_plan_info(plan.first)['private'] } + end + end + ",A full parse of the plan here on listing the plans will be expensive from both a computation and IO perspective. +576,"@@ -19,3 +19,9 @@ const ( + BUTTON3 = 15 + BUTTON4 = 16 + ) ++ ++// UART pins for NRF52840-DK ++const ( ++ UART_TX_PIN = 6 ++ UART_RX_PIN = 8 ++)","These constants use the `_PIN` suffix, while the other constants don't use it. I'm not sure what is best, but I would prefer to keep this consistent. Do you have an opinion on which it should be (with or without suffix)?" +577,"@@ -1089,6 +1089,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable { + ""Specifies the static node file containing the static nodes for this node to connect to"") + private final Path staticNodesFile = null; + ++ @SuppressWarnings({""FieldCanBeFinal"", ""FieldMayBeFinal""}) // PicoCLI requires non-final Strings. ++ @CommandLine.Option( ++ names = { ""--dns-discovery-url"" }, ++ description = ""Specifies the URL to use for DNS discovery"" ++ ) ++ private String dnsDiscoveryUrl = null; ++ + private EthNetworkConfig ethNetworkConfig; + private JsonRpcConfiguration jsonRpcConfiguration; + private GraphQLConfiguration graphQLConfiguration;",Hmm... this feels like discovery should come first. perhaps `--discovery-dns-url`? @NicolasMassart any opinions on this or ideas on who it should be run by? +578,"@@ -1,3 +1,4 @@ ++//go:build !ignore_autogenerated + // +build !ignore_autogenerated + + /*",why is this needed? +579,"@@ -23,7 +23,7 @@ DEFAULT_TYPE_ATTRIBUTES = ConfigTypeAttributes() + + + class ConfigType(object): +- def __init__(self, name=None, type_attributes=DEFAULT_TYPE_ATTRIBUTES, description=None): ++ def __init__(self, key, name, type_attributes=DEFAULT_TYPE_ATTRIBUTES, description=None): + + type_obj = type(self) + if type_obj in ConfigType.__cache:","I wonder if it'd be possible to autogenerate a key from the name within this function if one is not provided explicitly, rather than having all the callsites pass both the name and key (and usually as the same value)? Might give us a good place to implement a `name->key` function that isn't 1:1." +580,"@@ -110,6 +110,7 @@ public final class ThriftCodec implements Codec { + final Field IPV4 = new Field(TYPE_I32, 1); + final Field PORT = new Field(TYPE_I16, 2); + final Field SERVICE_NAME = new Field(TYPE_STRING, 3); ++ final Field IPV6 = new Field(TYPE_STRING, 4); + + @Override + public Endpoint read(ByteBuffer bytes) {",@adriancole I do not see a change in the thrift file. Are there unit tests verifying that this manual serialization is compatible with the native Thrift serialization done by classes generated from `.thrift` IDL file? +581,"@@ -506,7 +506,7 @@ Player* Game::getPlayerByGUID(const uint32_t& guid) + ReturnValue Game::getPlayerByNameWildcard(const std::string& s, Player*& player) + { + size_t strlen = s.length(); +- if (strlen == 0 || strlen > 20) { ++ if (strlen == 0 || strlen > PLAYER_NAME_LENGHT) { + return RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE; + } + ","spelling (variable name, all three changes)" +582,"@@ -411,8 +411,16 @@ type KeybaseService interface { + []keybase1.PublicKey, error) + + // LoadTeamPlusKeys returns a TeamInfo struct for a team with the +- // specified TeamID. +- LoadTeamPlusKeys(ctx context.Context, tid keybase1.TeamID) (TeamInfo, error) ++ // specified TeamID. The caller can specify `desiredKeyGen` to ++ // force a server check if that particular key gen isn't yet ++ // known; it may be set to UnspecifiedKeyGen if no server check is ++ // required. The caller can specify `desiredUID` to force a ++ // server check if that particular UID isn't a member of the team ++ // yet according to local caches; it may be set to """" if no server ++ // check is required. ++ LoadTeamPlusKeys(ctx context.Context, tid keybase1.TeamID, ++ desiredKeyGen KeyGen, desiredUser keybase1.UserVersion, ++ desiredRole keybase1.TeamRole) (TeamInfo, error) + + // CurrentSession returns a SessionInfo struct with all the + // information for the current session, or an error otherwise.","I believe you meant ""specify `desiredUID` and `desiredRole`""?" +583,"@@ -16,10 +16,9 @@ package openflow + + import ( + ""fmt"" ++ ""github.com/vmware-tanzu/antrea/pkg/apis/networking/v1beta1"" + ""net"" + +- coreV1 ""k8s.io/api/core/v1"" +- v1 ""k8s.io/api/networking/v1"" + ""k8s.io/klog"" + + ""github.com/vmware-tanzu/antrea/pkg/agent/types""","Please follow the import style, move it to its similar group" +584,"@@ -63,3 +63,18 @@ func IsUnrecognizedProcedureError(err error) bool { + _, ok := err.(errors.UnrecognizedProcedureError) + return ok + } ++ ++// UnrecognizedEncodingError returns an error for the given request, such that ++// IsUnrecognizedEncodingError can distinguish it from other errors coming out ++// of router.Choose. ++func UnrecognizedEncodingError(req *Request, want []string) error { ++ return errors.RouterUnrecognizedEncodingError(want, string(req.Encoding)) ++} ++ ++// IsUnrecognizedEncodingError returns true for errors returned by ++// Router.Choose if the router cannot find a handler for the request's ++// encoding. ++func IsUnrecognizedEncodingError(err error) bool { ++ _, ok := err.(errors.UnrecognizedEncodingError) ++ return ok ++}",Do we really need these? This is expanding on an API that we're about to do work on with the error stuff @kriskowal +585,"@@ -146,11 +146,9 @@ public class PasswordValidatorServiceBean implements java.io.Serializable { + * @return A List with error messages. Empty when the password is valid. + */ + public List validate(String password, Date passwordModificationTime, boolean isHumanReadable) { +-// public List validate(String password, boolean isHumanReadable) { + + init(); +- final PasswordData passwordData = PasswordData.newInstance(password, String.valueOf(passwordModificationTime.getTime()), null); +-// final PasswordData passwordData = PasswordData.newInstance(password, ""username"", null); ++ final PasswordData passwordData = new PasswordData(password); + final RuleResult result = new RuleResult(); + + for (PasswordValidator currentUser : validators.values()) {",passwordModificationTime is no longer used - did the change drop a time check that should be restored? Or should the param get dropped from the methods? +586,"@@ -40,7 +40,7 @@ namespace ScenarioMeasurement + + source.Kernel.ProcessStart += evt => + { +- if (processName.Equals(evt.ProcessName, StringComparison.OrdinalIgnoreCase) && pids.Contains(evt.ProcessID) && evt.CommandLine == commandLine) ++ if (processName.Equals(evt.ProcessName, StringComparison.OrdinalIgnoreCase) && pids.Contains(evt.ProcessID) && evt.CommandLine.Trim() == commandLine.Trim()) + { + if (pid.HasValue) + {","Would it break here without trim? If so, can we do trim in Startup.cs so we don't need to add this code to every parser?" +587,"@@ -115,7 +115,7 @@ var _ = Describe(""with running container"", func() { + It(""iptables should succeed in getting the lock after 3s"", func() { + iptCmd := cmdInContainer(""iptables"", ""-w"", ""3"", ""-A"", ""FORWARD"") + out, err := iptCmd.CombinedOutput() +- Expect(string(out)).To(ContainSubstring(""Another app is currently holding the xtables lock"")) ++ log.Printf(""iptables output='%s'"", out) + Expect(err).NotTo(HaveOccurred()) + }) + ","Since we're using Logrus, probably best to use `Infof` to avoid confusion (Logrus' Printf behaves differently to the built in one)" +588,"@@ -155,13 +155,14 @@ Blockly.FlyoutButton.prototype.createDom = function() { + this.svgGroup_); + svgText.textContent = this.text_; + +- this.width = svgText.getComputedTextLength() + +- 2 * Blockly.FlyoutButton.MARGIN; ++ this.width = svgText.getComputedTextLength(); + + if (!this.isLabel_) { ++ this.width += 2 * Blockly.FlyoutButton.MARGIN; + shadow.setAttribute('width', this.width); + shadow.setAttribute('height', this.height); + } ++ + rect.setAttribute('width', this.width); + rect.setAttribute('height', this.height); + ","Hm, this looks like a change that should go upstream as well." +589,"@@ -1533,16 +1533,6 @@ func (core *coreService) ChainID() uint32 { + return core.bc.ChainID() + } + +-// GetActionByActionHash returns action by action hash +-func (core *coreService) ActionByActionHash(h hash.Hash256) (action.SealedEnvelope, error) { +- if !core.hasActionIndex || core.indexer == nil { +- return action.SealedEnvelope{}, status.Error(codes.NotFound, blockindex.ErrActionIndexNA.Error()) +- } +- +- selp, _, _, _, err := core.getActionByActionHash(h) +- return selp, err +-} +- + // ReadContractStorage reads contract's storage + func (core *coreService) ReadContractStorage(ctx context.Context, addr address.Address, key []byte) ([]byte, error) { + ctx, err := core.bc.Context(ctx)",let's keep ActionByActionHash and delete getActionByActionHash +590,"@@ -64,4 +64,12 @@ class ProductVisibility + { + return $this->visible; + } ++ ++ /** ++ * @return \Shopsys\FrameworkBundle\Model\Pricing\Group\PricingGroup ++ */ ++ public function getPricingGroup(): PricingGroup ++ { ++ return $this->pricingGroup; ++ } + }",please use return type +591,"@@ -76,7 +76,7 @@ public class TestEdgeDriver extends RemoteWebDriver implements WebStorage, Locat + .findFirst().orElseThrow(WebDriverException::new); + + service = (EdgeDriverService) builder.withVerbose(true).withLogFile(logFile.toFile()).build(); +- LOG.info(""edgedriver will log to "" + logFile); ++ LOG.fine(""edgedriver will log to "" + logFile); + service.start(); + Runtime.getRuntime().addShutdownHook(new Thread(() -> service.stop())); + }",This is deliberately at this level. +592,"@@ -237,7 +237,7 @@ class UploadWorkerThread(TransferThread): + except self._retry_exceptions as e: + log.error(""Exception caught uploading part number %s for "" + ""vault %s, attempt: (%s / %s), filename: %s, "" +- ""exception: %s, msg: %s"", ++ ""exception: %s as msg: %s"", + work[0], self._vault_name, i + 1, self._num_retries + 1, + self._filename, e.__class__, e) + time.sleep(self._time_between_retries)","I'm going to go ahead and undo this change, I don't think it was intentional." +593,"@@ -163,7 +163,7 @@ namespace Datadog.AutoInstrumentation.ManagedLoader + /// As a result, the target framework moniker and the binary compatibility flags are initialized correctly. + ///
+ /// +- /// The above logic is further specialised, depending on the kind of the currnent AppDomain and where the app is hosted: ++ /// The above logic is further specialized, depending on the kind of the current AppDomain and where the app is hosted: + ///
+ /// * On non-default AD: + /// we do not wait.",> specialised This isn't a typo in my neck of the woods +594,"@@ -29,6 +29,7 @@ import ( + + var packages = []string{ + ""github.com/google/knative-gcp/test/cmd/target"", ++ ""github.com/google/knative-gcp/test/cmd/storageTarget"", + } + + var packageToImageConfig = map[string]string{}",will change to `storage_target` +595,"@@ -38,7 +38,7 @@ class SecurityCenterTest(unittest_utils.ForsetiTestCase): + """"""Set up."""""" + fake_global_configs = { + 'securitycenter': {'max_calls': 1, 'period': 1.1}} +- cls.securitycenter_beta_api_client = securitycenter.SecurityCenterClient(version='v1beta1') ++ cls.securitycenter = securitycenter.SecurityCenterClient(version='v1') + cls.project_id = 111111 + cls.source_id = 'organizations/111/sources/222' + ","This would be better as `cls.securitycenter_client`, to match what is being instantiated." +596,"@@ -34,6 +34,15 @@ import appModules + import watchdog + import extensionPoints + from fileUtils import getFileVersionInfo ++import shlobj ++from functools import wraps ++ ++# Path to the native system32 directory. ++nativeSys32: str = shlobj.SHGetFolderPath(None, shlobj.CSIDL.SYSTEM) ++# Path to the syswow64 directory if it exists on the current system. ++Syswow64Sys32: str = shlobj.SHGetFolderPath(None, shlobj.CSIDL.SYSTEMX86) ++# Do we have separate system32 directories for 32 and 64-bit processes? ++hasSeparateSyswow64: bool = nativeSys32 != Syswow64Sys32 + + #Dictionary of processID:appModule paires used to hold the currently running modules + runningTable={}",Could we have this initialization as part of the initialize method? +597,"@@ -15,7 +15,7 @@ export default AbstractEditController.extend({ + showUpdateButton: true, + + database: inject.service(), +- editController: inject.controller('patients/edit'), ++ editController: null, + filesystem: inject.service(), + + photoFileNotSet: computed('model.photoFile', function() {",This line should be removed as editController is not used from this context anymore. +598,"@@ -9,11 +9,17 @@ import ( + ""github.com/influxdata/flux/plan"" + ) + ++// Transformation represents functions that control of how the execution ++// engine will take in a flux Table, perform the necessary data processing ++// and return an output flux Table + type Transformation interface { + RetractTable(id DatasetID, key flux.GroupKey) error ++ // Process takes in a flux Table, performs data processing on it ++ // and produces an output flux Table + Process(id DatasetID, tbl flux.Table) error + UpdateWatermark(id DatasetID, t Time) error + UpdateProcessingTime(id DatasetID, t Time) error ++ // Finish indicates that the Transformation is complete + Finish(id DatasetID, err error) + } + ","This is correct in concept but the method signature doesn't really communicate the same thing. In other words, if the function produces an output table where is it? Its not on the function signature. Can you explain where the output table is created?" +599,"@@ -238,9 +238,14 @@ class DetectoRS_ResNet(ResNet): + pretrained=None, + init_cfg=None, + **kwargs): +- assert init_cfg is None, 'To prevent abnormal initialization ' \ +- 'behavior, init_cfg is not allowed to be set' +- self.pretrained = pretrained ++ self.init_cfg = init_cfg ++ if init_cfg is not None: # init_cfg priority > pretrained ++ self.pretrained = init_cfg['checkpoint'] ++ else: ++ if pretrained is not None: ++ self.pretrained = pretrained ++ else: ++ self.pretrained = None + self.sac = sac + self.stage_with_sac = stage_with_sac + self.rfp_inplanes = rfp_inplanes","For insurance, it's best not to take it directly" +600,"@@ -67,11 +67,11 @@ public abstract class AbstractWebDriverEventListener implements WebDriverEventLi + // Do nothing. + } + +- public void beforeChangeValueOf(WebElement element, WebDriver driver) { ++ public void beforeChangeValueOf(WebElement element, WebDriver driver, CharSequence[] value) { + // Do nothing. + } + +- public void afterChangeValueOf(WebElement element, WebDriver driver) { ++ public void afterChangeValueOf(WebElement element, WebDriver driver, CharSequence[] value) { + // Do nothing. + } + ","change 'value' to keysToSend, here and in other references in this commit. 'value' implies the user is getting the value of the element, rather than just the keys we're sending to it." +601,"@@ -1244,6 +1244,8 @@ func (engine *DockerTaskEngine) provisionContainerResources(task *apitask.Task, + taskIP := result.IPs[0].Address.IP.String() + seelog.Infof(""Task engine [%s]: associated with ip address '%s'"", task.Arn, taskIP) + engine.state.AddTaskIPAddress(taskIP, task.Arn) ++ task.SetLocalIPAddress(taskIP) ++ engine.saveTaskData(task) + return dockerapi.DockerContainerMetadata{ + DockerID: cniConfig.ContainerID, + }",is the plan to fully migrate to boltdb and then remove the state save here? +602,"@@ -153,6 +153,8 @@ function themeStyle(theme) { + + output.colorUrl = '#7B81FF'; + ++ output.strongTextColor = 'rgb(220,220,220)'; ++ + themeCache_[theme] = output; + return addExtraStyles(themeCache_[theme]); + }",This should be `output.colorBright`. Unless I'm missing some reason for adding a new theme variable. +603,"@@ -6,6 +6,11 @@ + + import os + ++version_year=2016 ++version_major=3 ++version_minor=0 ++version_build=0 ++ + def _updateVersionFromVCS(): + """"""Update the version from version control system metadata if possible. + """"""","nit: I wonder if these should be moved down to where version is defined, just to keep them all in the same place." +604,"@@ -99,7 +99,7 @@ const LanguageParameters& GetLangParams(IDLOptions::Language lang) { + """", + """", + """", +- ""import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"" ++ ""import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\nimport javax.annotation.*;\n"" + ""import com.google.flatbuffers.*;\n\n@SuppressWarnings(\""unused\"")\n"", + { + ""/**"",",Is this supported by every implementation of Java (and Android)? Should it be conditional upon `gen_nullable`? +605,"@@ -50,8 +50,8 @@ class Phase < ActiveRecord::Base + has_many :suffix_sections, -> (phase) { + modifiable.where(<<~SQL, phase_id: phase.id, modifiable: false) + sections.number > (SELECT MAX(number) FROM sections +- WHERE sections.modifiable = :modifiable) +- AND sections.phase_id = :phase_id ++ WHERE sections.modifiable = :modifiable ++ AND sections.phase_id = :phase_id) + SQL + }, class_name: ""Section"" + ",@briri Thanks! I just caught this too updating my feature branch +606,"@@ -214,8 +214,17 @@ var errorConfigFileNotFound = errors.New(""config file not found"") + // automatically decrypt it. + func loadConfigFile() (*goconfig.ConfigFile, error) { + b, err := ioutil.ReadFile(ConfigPath) ++ envpw := os.Getenv(""RCLONE_CONFIG_PASS"") + if err != nil { + if os.IsNotExist(err) { ++ if len(configKey) == 0 && envpw != """" { ++ err := setConfigPassword(envpw) ++ if err != nil { ++ fmt.Println(""Using RCLONE_CONFIG_PASS returned:"", err) ++ } else { ++ fs.Debugf(nil, ""Using RCLONE_CONFIG_PASS password."") ++ } ++ } + return nil, errorConfigFileNotFound + } + return nil, err","I think you should move this block (and the `envpw := os.Getenv(""RCLONE_CONFIG_PASS"")`) right to the start of the function, then we can remove the duplicate code below" +607,"@@ -424,6 +424,17 @@ public class NodeTest { + return baseDir; + } + ++ //Test that the draining command sets Host status to DRAINING ++ @Test ++ public void drainingNodeStatusDraining() { ++ ++ } ++ ++ //Test that a draining node doesn't accept new sessions by any means ++ //Test that a draining node continues to run its sessions and accept new WebDriver commands ++ //Test that a node will shut down once all sessions are finished ++ //Test that RemoteNode will post the correct command oto the LocalNode ++ + private CreateSessionRequest createSessionRequest(Capabilities caps) { + return new CreateSessionRequest( + ImmutableSet.copyOf(Dialect.values()),",Is this only to set the node to draining? I think we can do that inside `Before` or something? +608,"@@ -647,6 +647,11 @@ namespace Datadog.Trace + { + try + { ++ if (AzureAppServices.Metadata.IsRelevant) ++ { ++ return AzureAppServices.Metadata.SiteName; ++ } ++ + if (TryLoadAspNetSiteName(out var siteName)) + { + return siteName;",This should have been moved up above this inner `try` because the log message in the `catch` block does not apply to this. +609,"@@ -43,12 +43,13 @@ module Bolt + Bolt::ResultSet.include_iterable + end + +- # Create a top-level alias for TargetSpec so that users don't have to ++ # Create a top-level alias for TargetSpec and PlanResult so that users don't have to + # namespace it with Boltlib, which is just an implementation detail. This +- # allows TargetSpec to feel like a built-in type in bolt, rather than ++ # allows them to feel like a built-in type in bolt, rather than + # something has been, no pun intended, ""bolted on"". +- def add_target_spec(compiler) ++ def alias_types(compiler) + compiler.evaluate_string('type TargetSpec = Boltlib::TargetSpec') ++ compiler.evaluate_string('type PlanResult = Boltlib::PlanResult') + end + + def full_modulepath(modulepath)",Do we expect people to use PlanResult directly? +610,"@@ -48,7 +48,8 @@ func NewBackoff() wait.Backoff { + + // WaitForWithRetryable repeats a condition check with exponential backoff. + func WaitForWithRetryable(backoff wait.Backoff, condition wait.ConditionFunc, retryableErrors ...string) error { //nolint +- return wait.ExponentialBackoff(backoff, func() (bool, error) { ++ var actualErr error ++ waitErr := wait.ExponentialBackoff(backoff, func() (bool, error) { + ok, err := condition() + if ok { + // All done!",Maybe we should call this something like `errToReturn`? +611,"@@ -215,7 +215,8 @@ func (p *Protocol) GrantEpochReward( + } + + // Reward additional bootstrap bonus +- if epochNum <= a.foundationBonusLastEpoch { ++ fairBankEpochNum := rp.GetEpochNum(hu.FairbankBlockHeight()) // extend foundation bonus from fairbank to fairbank + 1 year ++ if epochNum <= a.foundationBonusLastEpoch || (epochNum >= fairBankEpochNum && epochNum <= fairBankEpochNum+a.foundationBonusLastEpoch) { + for i, count := 0, uint64(0); i < len(candidates) && count < a.numDelegatesForFoundationBonus; i++ { + if _, ok := exemptAddrs[candidates[i].Address]; ok { + continue","should calculate numEpochIn1Year = xxx and <= fairBankEpochNum+numEpochIn1Year a.foundationBonusLastEpoch just happens to be equal to 1 year now, but should not count on that" +612,"@@ -350,14 +350,17 @@ const htmlElms = { + }, + usemap: { + matches: '[usemap]', +- contentTypes: ['interactive', 'embedded', 'phrasing', 'flow'] ++ contentTypes: ['interactive', 'embedded', 'flow'] + }, + default: { + // Note: allow role presentation and none on image with no + // alt as a way to prevent axe from flagging the image as + // needing an alt + allowedRoles: ['presentation', 'none'], +- contentTypes: ['embedded', 'phrasing', 'flow'] ++ // Note: spec change (do not count as phrasing), because browsers ++ // insert a space between an img's accessible name and other ++ // elements' accessible names ++ contentTypes: ['embedded', 'flow'] + } + }, + // 5.10 img Element",I wasn't sure if the content type needed to be removed from both the `default` and `usemap` objects - I'm not sure how usemap is used. +613,"@@ -20,11 +20,13 @@ + """""" + Geneve: Generic Network Virtualization Encapsulation + +-draft-ietf-nvo3-geneve-06 ++draft-ietf-nvo3-geneve-16 + """""" + ++import struct ++ + from scapy.fields import BitField, XByteField, XShortEnumField, X3BytesField, \ +- XStrField ++ XStrField, XShortField, StrField, XByteField, FieldLenField, PacketListField + from scapy.packet import Packet, bind_layers + from scapy.layers.inet import IP, UDP + from scapy.layers.inet6 import IPv6","Duplication of line 28 Please refer your tox -e flake8 It seems that XStrField, XShortField, FieldLenField are not used" +614,"@@ -630,6 +630,18 @@ class FilenamePrompt(_BasePrompt): + + self._to_complete = '' + ++ def _directories_hide_show_model(self, path): ++ """"""Get rid of non-matching directories."""""" ++ try: ++ num_rows = self._file_model.rowCount(self._root_index) ++ for row in range(num_rows): ++ index = self._file_model.index(row, 0, self._file_model.index(path)) ++ hidden = self._to_complete not in index.data() ++ self._file_view.setRowHidden(index.row(), index.parent(), hidden) ++ except FileNotFoundError: ++ log.prompt.debug(""Directory doesn't exist, can't \ ++ hide and unhide file prompt folders"") ++ + @pyqtSlot(str) + def _set_fileview_root(self, path, *, tabbed=False): + """"""Set the root path for the file display.""""""","I don't really understand the `self._file_model.index(path)` as parent here - you use `self._root_index` for `rowCount` above, so wouldn't the parent here need to be `self._root_index` as well?" +615,"@@ -75,6 +75,8 @@ public class DirectSpellChecker { + private float thresholdFrequency = 0f; + /** minimum length of a query word to return suggestions */ + private int minQueryLength = 4; ++ /** maximum length of a query word to return suggestions */ ++ private int maxQueryLength = 0; + /** value in [0..1] (or absolute number >= 1) representing the maximum + * number of documents (of the total) a query term can appear in to + * be corrected. */",Do we want validation somewhere that max >= min? Or simply treat the max < min case as ignoring max? +616,"@@ -81,7 +81,7 @@ namespace NLog.LayoutRenderers + { + if (TopFrames == 1) + { +- // Allows fast rendering of ${when:when='${ndc:topframes=1}' == '':inner=:else=${ndc}|} ++ // Allows fast rendering of ${ndc:topframes=1} + var topFrame = NestedDiagnosticsContext.PeekObject(); + if (topFrame != null) + AppendAsString(topFrame, GetFormatProvider(logEvent), builder);",:+1: that's a easier example :) +617,"@@ -117,4 +117,9 @@ interface ProductQueryInterface + * @return AttributeId[] + */ + public function findAttributeIdsByProductId(ProductId $productId): array; ++ ++ /** ++ * @return array ++ */ ++ public function findProductIdsWithBoundAttributeByAttributeId(AggregateId $id): array; + }","If an external module decorates this interface, such a change will cause it to generate an error" +618,"@@ -254,7 +254,7 @@ static int jobtap_remove (struct jobtap *jobtap, + while (p) { + const char *name = jobtap_plugin_name (p); + if (all +- || (isglob && fnmatch (arg, name, 0) == 0) ++ || (isglob && fnmatch (arg, name, FNM_PERIOD) == 0) + || strcmp (arg, name) == 0) { + zlistx_detach_cur (jobtap->plugins); + flux_plugin_destroy (p);","Oh ha hah, FNM_PERIOD worked out nicely there. Points for co-opting a file system convention." +619,"@@ -7,11 +7,12 @@ + package action + + import ( ++ ""encoding/hex"" + ""fmt"" +- ""math/big"" +- + ""github.com/spf13/cobra"" + ""go.uber.org/zap"" ++ ""math/big"" ++ ""strings"" + + ""github.com/iotexproject/iotex-core/action"" + ""github.com/iotexproject/iotex-core/cli/ioctl/cmd/account""","wrong grouping. As you can tell from the other files, we put system packages in the first group, the 3rd party packages in the second group, and our own packages in the third group." +620,"@@ -78,8 +78,10 @@ func newJobLogOpts(vars jobLogsVars) (*jobLogsOpts, error) { + // Validate returns an error if the values provided by flags are invalid. + func (o *jobLogsOpts) Validate() error { + if o.appName != """" { +- _, err := o.configStore.GetApplication(o.appName) +- if err != nil { ++ if _, err := o.configStore.GetApplication(o.appName); err != nil { ++ return err ++ } ++ if _, err := o.configStore.GetJob(o.appName, o.name); err != nil { + return err + } + }",Is `o.name` always set here? +621,"@@ -73,7 +73,8 @@ func dependenciesCanBeResolved(target *api.Container, by []*api.Container) bool + } + + return verifyStatusResolvable(target, nameMap, neededVolumeContainers, volumeCanResolve) && +- verifyStatusResolvable(target, nameMap, linksToContainerNames(target.Links), linkCanResolve) ++ verifyStatusResolvable(target, nameMap, linksToContainerNames(target.Links), linkCanResolve) && ++ verifyStatusResolvable(target, nameMap, target.SteadyStateDependencies, onSteadyStateCanResolve) + } + + // DependenciesAreResolved validates that the `target` container can be","Can this line be removed, as `SteadyStateDependencies` isn't updated anywhere? Also do we need to check the `TransitionDependencySet` here?" +622,"@@ -73,7 +73,7 @@ class User < ActiveRecord::Base + end + + def eligible_for_annual_upgrade? +- plan.present? && plan.has_annual_plan? ++ has_active_subscription? && plan.present? && plan.has_annual_plan? + end + + def annualized_payment","`plan.present?` and `has_active_subscription?` are equivalent. We can drop this change, while leaving the one on `app/controllers/application_controller.rb`." +623,"@@ -100,6 +100,7 @@ class Command: + if scope != 'global' and instance is None: + raise ValueError(""Setting scope without setting instance makes "" + ""no sense!"") ++ # pylint: enable=too-many-locals + + self.name = name + self.maxsplit = maxsplit","No need for this, as pylint already only turns things off for this function and it's needed for the entire function." +624,"@@ -188,7 +188,7 @@ func (c *Operator) bootstrap(ctx context.Context) error { + } + c.secrInfs, err = informers.NewInformersForResource( + informers.NewKubeInformerFactories( +- c.config.Namespaces.AllowList, ++ c.config.Namespaces.AlertmanagerConfigAllowList, + c.config.Namespaces.DenyList, + c.kclient, + resyncPeriod,",L171 needs to be modified too? +625,"@@ -19,6 +19,16 @@ See the file COPYING for details. + #include + #include + ++int dag_node_comp(void *item, const void *arg) ++{ ++ struct dag_node *d = ((struct dag_node *) item); ++ struct dag_node *e = ((struct dag_node *) arg); ++ ++ if(d->nodeid == e->nodeid) ++ return 1; ++ return 0; ++} ++ + struct dag_node *dag_node_create(struct dag *d, int linenum) + { + struct dag_node *n;","Why do you compare by nodeid? Simply saying d == e should be enough. Unless we have to objects in memory with the same nodeid. If that is so, something went really wrong." +626,"@@ -0,0 +1,18 @@ ++_base_ = [ ++ '../_base_/models/retinanet_r50_fpn.py', ++ '../_base_/datasets/coco_detection.py', ++ '../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py' ++] ++model = dict( ++ type='RetinaNet', ++ backbone=dict( ++ _delete_=True, ++ type='PyramidVisionTransformer', ++ num_layers=[2, 2, 2, 2], ++ init_cfg=dict( ++ type='Pretrained', ++ checkpoint='https://github.com/whai362/PVT/' ++ 'releases/download/v2/pvt_tiny.pth')), ++ neck=dict(in_channels=[64, 128, 320, 512])) ++# optimizer ++optimizer = dict(_delete_=True, type='AdamW', lr=0.0001, weight_decay=0.0001)",configs/pvt/retinanet_pvt_t_fpn_1x_coco.py --> configs/pvt/retinanet_pvt-t_fpn_1x_coco.py +627,"@@ -20,7 +20,7 @@ type MetadataResponse struct { + + type TaskResponse struct { + Arn string +- DesiredStatus string ++ DesiredStatus string `json:""DesiredStatus,omitempty""` + KnownStatus string + Family string + Version string","Nit, this could be json:"",omitempty""" +628,"@@ -113,7 +113,12 @@ func tplDirName(s string) string { + return filepath.Dir(s) + } + +-//BuildArgs returns a docker.BuildArguments object given a ws root directory. ++// BuildRequired returns if the service requires building from the local Dockerfile. ++func (s *LoadBalancedWebService) BuildRequired() (bool, error) { ++ return buildRequired(s.Image.Image) ++} ++ ++// BuildArgs returns a docker.BuildArguments object given a ws root directory. + func (s *LoadBalancedWebService) BuildArgs(wsRoot string) *DockerBuildArgs { + return s.Image.BuildConfig(wsRoot) + }",It's kinda funny to read `s.Image.Image` I wonder why it resulted to this way. What would it take to refactor to just `s.Image`? +629,"@@ -1,4 +1,4 @@ +-// +build integration ++// +build integration,deploy + + // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + // SPDX-License-Identifier: Apache-2.0",nit: I like the idea! can we instead change the tag to `integration-remote` to be more specific? I feel like it's possible for us to use the `deploy` build tag for possibly another scenario +630,"@@ -4701,8 +4701,8 @@ XS(XS_Mob_HasNPCSpecialAtk) { + XS(XS_Mob_SendAppearanceEffect); /* prototype to pass -Wmissing-prototypes */ + XS(XS_Mob_SendAppearanceEffect) { + dXSARGS; +- if (items < 2 || items > 7) +- Perl_croak(aTHX_ ""Usage: Mob::SendAppearanceEffect(THIS, int32 param_1, [int32 param_2 = 0], [int32 param_3 = 0], [int32 param_4 = 0], [int32 param_5 = 0], [Client* single_client_to_send_to = null])""); // @categories Script Utility ++ if (items < 2 || items > 17) ++ Perl_croak(aTHX_ ""Usage: Mob::SendAppearanceEffect(THIS, int32 effect1, [int32 effect2 = 0], [int32 effect3 = 0], [int32 effect4 = 0], [int32 effect5 = 0], [Client* single_client_to_send_to = null]), [uint32 slot1 = 1], [uint32 ground1 = 1], [uint32 slot2 = 1], [uint32 ground2 = 1], [uint32 slot3 = 1], [uint32 ground2 = 1], [uint32 slot4 = 1], [uint32 ground4 = 1], [uint32 slot5 = 1], [uint32 ground5 = 1]""); // @categories Script Utility + { + Mob *THIS; + int32 parm1 = (int32) SvIV(ST(1));",Copy and paste error here. Edit: Also missing commas here and in other Perl croaks between some parameters and not others. +631,"@@ -16,11 +16,12 @@ + + using System.Collections.Generic; + using Nethermind.Core; ++using Nethermind.Core.Crypto; + + namespace Nethermind.Consensus + { + public interface IPendingTxSelector + { +- IEnumerable SelectTransactions(long gasLimit); ++ IEnumerable SelectTransactions(Keccak stateRoot, long gasLimit); + } + }",stateRoot or maybe ParentHeader would make more sense from API point of view? +632,"@@ -151,7 +151,6 @@ public class PlaybackServiceFlavorHelper { + // hardware volume buttons control the local device volume + mediaRouter.setMediaSessionCompat(null); + unregisterWifiBroadcastReceiver(); +- callback.setupNotification(false, info); + } + }; + }",Are you sure that this is no longer needed? +633,"@@ -57,7 +57,11 @@ class BaseTableScan implements TableScan { + private static final Logger LOG = LoggerFactory.getLogger(TableScan.class); + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(""yyyy-MM-dd HH:mm:ss.SSS""); +- private static final List SNAPSHOT_COLUMNS = ImmutableList.of( ++ private static final List SCAN_COLUMNS = ImmutableList.of( ++ ""snapshot_id"", ""file_path"", ""file_ordinal"", ""file_format"", ""block_size_in_bytes"", ++ ""file_size_in_bytes"", ""record_count"", ""partition"" ++ ); ++ private static final List SCAN_WITH_STATS_COLUMNS = ImmutableList.of( + ""snapshot_id"", ""file_path"", ""file_ordinal"", ""file_format"", ""block_size_in_bytes"", + ""file_size_in_bytes"", ""record_count"", ""partition"", ""value_counts"", ""null_value_counts"", + ""lower_bounds"", ""upper_bounds""","Would it help to use SCAN_COLUMNS as base to build SCAN_WITH_STATS_COLUMNS e.g like so `SCAN_WITHSTATS_COLUMNS = ImmutableList.builder().addAll(SCAN_COLUMNS).add(""value_counts"",....).build()` ?" +634,"@@ -85,11 +85,19 @@ func (a *PipedAPI) Register(server *grpc.Server) { + + // Ping is periodically sent to report its realtime status/stats to control-plane. + // The received stats will be pushed to the metrics collector. ++// Note: This service is deprecated, use ReportStat instead. + func (a *PipedAPI) Ping(ctx context.Context, req *pipedservice.PingRequest) (*pipedservice.PingResponse, error) { + return &pipedservice.PingResponse{}, nil + // return nil, status.Error(codes.Unimplemented, """") + } + ++// ReportStat is periodically sent to report its realtime status/stats to control-plane. ++// The received stats will be pushed to the metrics collector. ++func (a *PipedAPI) ReportStat(ctx context.Context, req *pipedservice.ReportStatRequest) (*pipedservice.ReportStatResponse, error) { ++ return &pipedservice.ReportStatResponse{}, nil ++ // return nil, status.Error(codes.Unimplemented, """") ++} ++ + // ReportPipedMeta is sent by piped while starting up to report its metadata + // such as configured cloud providers. + func (a *PipedAPI) ReportPipedMeta(ctx context.Context, req *pipedservice.ReportPipedMetaRequest) (*pipedservice.ReportPipedMetaResponse, error) {",`ctx` is unused in ReportStat +635,"@@ -21,12 +21,15 @@ + #include + #include + #include ++#include ++#include + + #include + #include + #include + #include + #include ++ + #include ""t_generator.h"" + #include ""platform.h"" + #include ""version.h""",We don't want to add boost as a dependency when building the Thrift compiler. Sorry. +636,"@@ -323,7 +323,8 @@ bool Monsters::deserializeSpell(const pugi::xml_node& node, spellBlock_t& sb, co + combat->setParam(COMBAT_PARAM_TYPE, COMBAT_HEALING); + combat->setParam(COMBAT_PARAM_AGGRESSIVE, 0); + } else if (tmpName == ""speed"") { +- int32_t speedChange = 0; ++ int32_t minSpeedChange = 0; ++ int32_t maxSpeedChange = 0; + int32_t duration = 10000; + + if ((attr = node.attribute(""duration""))) {",It's not printing the range. Also I think it's useful to print a warning above stating that the minimum change is -1000. +637,"@@ -332,3 +332,15 @@ func (c *clusterClient) SchedPolicyDelete(name string) error { + + return nil + } ++ ++// SchedPolicyGet returns schedule policy matching given name. ++func (c *clusterClient) SchedPolicyGet(name string) (*sched.SchedPolicy, error) { ++ policy := new(sched.SchedPolicy) ++ req := c.c.Get().Resource(clusterPath + SchedPath + ""/"" + name) ++ ++ if err := req.Do().Unmarshal(policy); err != nil { ++ return nil, err ++ } ++ ++ return policy, nil ++}",if name is empty will this become enumerate ? (and cause the unmarshal to fail ?) +638,"@@ -15,7 +15,7 @@ module ProductsHelper + if current_user_has_access_to?(:exercises) + link_to url, options, &block + else +- content_tag ""a"", &block ++ link_to edit_subscription_path, options, &block + end + end + end",How about including a flash message that explains the exercises are only available to subscribers of X plan? +639,"@@ -232,6 +232,11 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit): + Enter/Shift+Enter/etc. will cause QLineEdit to think it's finished + without command_accept to be called. + """""" ++ text = self.text() ++ if text in modeparsers.STARTCHARS and e.key() == Qt.Key_Backspace: ++ modeman.leave(self._win_id, usertypes.KeyMode.command, ++ 'prefix deleted') ++ + if e.key() == Qt.Key_Return: + e.ignore() + return",You should also call `e.accept()` and `return` so the key press isn't processed further (as we're leaving insert mode anyways). +640,"@@ -0,0 +1,14 @@ ++MAIL_SETTINGS = { ++ address: ""smtp.sendgrid.net"", ++ port: ""587"", ++ authentication: :plain, ++ user_name: ENV[""SENDGRID_USERNAME""], ++ password: ENV[""SENDGRID_PASSWORD""], ++ domain: ""heroku.com"" ++} ++ ++if ENV[""EMAIL_RECIPIENTS""] ++ Mail.register_interceptor( ++ RecipientInterceptor.new(ENV.fetch(""EMAIL_RECIPIENTS"")), ++ ) ++end",Freeze mutable objects assigned to constants. +641,"@@ -34,8 +34,11 @@ import { + + async function toggleOptIn() { + await page.waitForSelector( '#googlesitekit-opt-in' ); +- await expect( page ).toClick( '#googlesitekit-opt-in' ); +- await page.waitForResponse( ( res ) => res.url().match( 'wp/v2/users/me' ) ); ++ await pageWait(); ++ await Promise.all( [ ++ page.waitForResponse( ( res ) => res.url().match( 'wp/v2/users/me' ) ), ++ expect( page ).toClick( '#googlesitekit-opt-in' ), ++ ] ); + } + + describe( 'management of tracking opt-in/out via settings page', () => {","Hmm, this feels hacky. Maybe good enough if it makes the test more stable, but why is timing even an aspect here, since below it should wait for these two things anyway?" +642,"@@ -144,6 +144,12 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation + { + activity.SetTag(SemanticConventions.AttributeHttpUserAgent, userAgent); + } ++ ++ var xForwardedFor = request.Headers[""X-Forwarded-For""].FirstOrDefault(); ++ if (!string.IsNullOrEmpty(xForwardedFor)) ++ { ++ activity.SetTag(SemanticConventions.AttributeHttpClientIP, xForwardedFor.Split(',').First().Trim()); ++ } + } + } + ","Do we want this on by default, or an opt-in (e.g. via some config while add the instrumentation)? I guess a more general question is - what's the bar for the default vs opt-in tags." +643,"@@ -91,7 +91,7 @@ int main(int argc, char *argv[]) { + } + + LOG(INFO) << ""Starting Graph HTTP Service""; +- nebula::WebService::registerHandler(""/graph"", [] { ++ nebula::WebService::registerHandler(""/status"", [] { + return new nebula::graph::GraphHttpHandler(); + }); + status = nebula::WebService::start();","`status` is just one of the features, named as status is not suitable." +644,"@@ -296,9 +296,17 @@ public class NavListAdapter extends BaseAdapter + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + convertView = inflater.inflate(R.layout.nav_section_item, parent, false); ++ TextView feedsFilteredMsg = convertView.findViewById(R.id.nav_feeds_filtered_message); + +- convertView.setEnabled(false); +- convertView.setOnClickListener(null); ++ if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE) { ++ convertView.setEnabled(true); ++ feedsFilteredMsg.setText(""{md-info-outline} "" + context.getString(R.string.feed_is_filtered)); ++ Iconify.addIcons(feedsFilteredMsg); ++ feedsFilteredMsg.setVisibility(View.VISIBLE); ++ } else { ++ convertView.setEnabled(false); ++ feedsFilteredMsg.setVisibility(View.GONE); ++ } + + return convertView; + }","There is an option to hide the subscriptions list from the sidebar. If it is hidden, the filter text should not be displayed." +645,"@@ -224,6 +224,11 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable { + queryResultWindowSize = Math.max(1, getInt(""query/queryResultWindowSize"", 1)); + queryResultMaxDocsCached = getInt(""query/queryResultMaxDocsCached"", Integer.MAX_VALUE); + enableLazyFieldLoading = getBool(""query/enableLazyFieldLoading"", false); ++ ++ useCircuitBreakers = getBool(""query/useCircuitBreakers"", false); ++ memoryCircuitBreakerThreshold = getInt(""query/memoryCircuitBreakerThreshold"", 100); ++ ++ validateMemoryBreakerThreshold(); + + useRangeVersionsForPeerSync = getBool(""peerSync/useRangeVersions"", true); + ","I'd like for all of this to be dynamically configurable at some point, but it doesn't have to be in this PR. Can add it to the future SIP or create a separate JIRA for it, as you think would be appropriate." +646,"@@ -57,8 +57,6 @@ extern Events* g_events; + extern Chat* g_chat; + extern LuaEnvironment g_luaEnvironment; + +-using ErrorCode = boost::system::error_code; +- + Signals::Signals(boost::asio::io_service& service) : + set(service) + {",move the constructor to down the `namespace` +647,"@@ -123,6 +123,10 @@ type ClusterDeploymentStatus struct { + // Federated is true if the cluster deployment has been federated with the host cluster. + Federated bool `json:""federated,omitempty""` + ++ // FederatedClusterRef is the reference to the federated cluster resource associated with ++ // this ClusterDeployment ++ FederatedClusterRef *corev1.ObjectReference `json:""federatedClusterRef,omitempty""` ++ + // AdminKubeconfigSecret references the secret containing the admin kubeconfig for this cluster. + AdminKubeconfigSecret corev1.LocalObjectReference `json:""adminKubeconfigSecret,omitempty""` + ",Nit: ending with a '.' looks consistent with the fields around it. +648,"@@ -138,7 +138,7 @@ func (s *Service) MintX509SVID(ctx context.Context, req *svidv1.MintX509SVIDRequ + } + + func (s *Service) MintJWTSVID(ctx context.Context, req *svidv1.MintJWTSVIDRequest) (*svidv1.MintJWTSVIDResponse, error) { +- rpccontext.AddRPCAuditFields(ctx, s.fieldsFromJWTSvidParams(req.Id, req.Audience, req.Ttl)) ++ rpccontext.AddRPCAuditFields(ctx, s.fieldsFromJWTSvidParams(ctx, req.Id, req.Audience, req.Ttl)) + jwtsvid, err := s.mintJWTSVID(ctx, req.Id, req.Audience, req.Ttl) + if err != nil { + return nil, err","Audit log will not have a warning about they are using a deprecated path, is it something we must care about?" +649,"@@ -23,7 +23,7 @@ namespace Microsoft.Cci.Differs.Rules + // If implementation is protected then contract must be protected as well. + if (impl.Visibility == TypeMemberVisibility.Family) + { +- if (contract.Visibility != TypeMemberVisibility.Family) ++ if (contract.Visibility != TypeMemberVisibility.Family && contract.Visibility != TypeMemberVisibility.FamilyOrAssembly) + { + differences.AddIncompatibleDifference(this, + ""Visibility of member '{0}' is '{1}' in the implementation but '{2}' in the contract."",",I think you also want to update the condition to add ` || impl.Visibility == TypeMemberVisibility.FamilyOrAssembly`. +650,"@@ -18,7 +18,10 @@ import ( + ) + + var ( +- depositToRewardingFundBaseGas = uint64(10000) ++ // DepositToRewardingFundBaseGas represents the base intrinsic gas for depositToRewardingFund ++ DepositToRewardingFundBaseGas = uint64(10000) ++ // DepositToRewardingFundGasPerByte represents the depositToRewardingFund payload gas per uint ++ DepositToRewardingFundGasPerByte = uint64(100) + ) + + // DepositToRewardingFund is the action to deposit to the rewarding fund",`DepositToRewardingFundBaseGas` is a global variable (from `gochecknoglobals`) +651,"@@ -3,12 +3,14 @@ + // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + // SPDX-License-Identifier: Apache-2.0 + +-// Package groups contains the names of command groups ++// Package groups contains the names of command groups. + package group + ++// Categories for each top level command in the CLI. + const ( +- GettingStarted = ""Getting Started ✨"" +- Develop = ""Develop 🔧"" ++ GettingStarted = ""Getting Started 🌱"" ++ Develop = ""Develop ✨"" + Settings = ""Settings ⚙️"" ++ Operational = ""Operational 🧐"" + Release = ""Release 🚀"" + )","What do you think of ""operations""?? Also what do these emojis look like on Linux??" +652,"@@ -0,0 +1,16 @@ ++<% content_for :subject_block do %> ++

<%= t('shared.subscription.name') %> for Teams

++

++ Sign your team up for <%= t('shared.subscription.name') %> today, and give them the finest Ruby on Rails content and the best expert teachers. ++

++<% end %> ++ ++

Your team gets all of the great benefits of <%= link_to t('shared.subscription.name'), prime_path %>, with convenient monthly group billing, as well as a nice discount. <%= t('shared.subscription.name') %> Teams have a minimum of 5 members, and a 10% discount off the normal price. New members can be added at any time.

++ ++
++ <%= render @plans %> ++
++ ++ ++ <%= link_to ""View all the features of #{t('shared.subscription.name')}"", prime_path %> ++","I like the word ""give"" here. Feels like I'm giving a gift to my team." +653,"@@ -11,12 +11,16 @@ import numpy as np + from sklearn import __version__ as sk_version + from sklearn.base import clone + from sklearn.datasets import (load_boston, load_breast_cancer, load_digits, +- load_iris, load_svmlight_file) ++ load_iris, load_linnerud, load_svmlight_file, ++ make_multilabel_classification) + from sklearn.exceptions import SkipTestWarning + from sklearn.metrics import log_loss, mean_squared_error +-from sklearn.model_selection import GridSearchCV, train_test_split ++from sklearn.model_selection import GridSearchCV, RandomizedSearchCV, train_test_split ++from sklearn.multioutput import (MultiOutputClassifier, ClassifierChain, MultiOutputRegressor, ++ RegressorChain) + from sklearn.utils.estimator_checks import (_yield_all_checks, SkipTest, + check_parameters_default_constructible) ++from scipy.stats import randint, uniform + + + decreasing_generator = itertools.count(0, -1)",Is it possible to use `np.random` module instead? +654,"@@ -49,7 +49,7 @@ legend_dimensions = ['label_standoff', 'label_width', 'label_height', 'glyph_wid + + class ElementPlot(BokehPlot, GenericElementPlot): + +- bgcolor = param.Parameter(default='white', doc="""""" ++ bgcolor = param.Parameter(default=None, allow_None=True, doc="""""" + Background color of the plot."""""") + + border = param.Number(default=10, doc=""""""","``default=None`` implies ``allow_None`` so ``allow_None`` is superfluous here. As a special case, if allow_None=True (which is true by default if the parameter has a default of None when declared) then a value of None is also allowed." +655,"@@ -551,8 +551,8 @@ func genClientCerts(config *config.Control, runtime *config.ControlRuntime) erro + if _, err = factory(""system:kube-proxy"", nil, runtime.ClientKubeProxyCert, runtime.ClientKubeProxyKey); err != nil { + return err + } +- // this must be hardcoded to k3s-controller because it's hard coded in the rolebindings.yaml +- if _, err = factory(""system:k3s-controller"", nil, runtime.ClientK3sControllerCert, runtime.ClientK3sControllerKey); err != nil { ++ // This user (system:k3s-controller by default) must be bound to a role in rolebindings.yaml or the downstream equivalent ++ if _, err = factory(""system:""+version.Program+""-controller"", nil, runtime.ClientK3sControllerCert, runtime.ClientK3sControllerKey); err != nil { + return err + } + ",Is there anything in particular that makes setting up the downstream rolebinding(s) to `system:k3s-controller` burdensome or confusing? This changes looks fine to me but it seems a shame to alias an embedded k3s controller. If we are doing this in other places that I am not aware of then we can dismiss this concern out of hand. +656,"@@ -21,7 +21,7 @@ import ( + ""strings"" + ""time"" + +- acd ""github.com/ncw/go-acd"" ++ ""github.com/ncw/go-acd"" + ""github.com/ncw/rclone/fs"" + ""github.com/ncw/rclone/fs/config"" + ""github.com/ncw/rclone/fs/config/configmap""",File is not `goimports`-ed (from `goimports`) +657,"@@ -0,0 +1,15 @@ ++// Licensed to the .NET Foundation under one or more agreements. ++// The .NET Foundation licenses this file to you under the MIT license. ++// See the LICENSE file in the project root for more information. ++ ++namespace Reporting ++{ ++ public class Os ++ { ++ public string Locale { get; set; } ++ ++ public string Architecture { get; set; } ++ ++ public string Name { get; set; } ++ } ++}","nit: all other types in this project have full names, so maybe a better name would be `OperatingSystem`?" +658,"@@ -16,7 +16,7 @@ + #include + #include + #include +-#include ""MolTransforms.h"" ++#include + + using namespace RDKit; + using namespace MolTransforms;",Why is this needed here? +659,"@@ -192,7 +192,7 @@ public interface Context { + methodUsage = ((TypeVariableResolutionCapability) methodDeclaration) + .resolveTypeVariables(this, argumentsTypes); + } else { +- throw new UnsupportedOperationException(); ++ return Optional.empty(); + } + + return Optional.of(methodUsage);","mmm, why a method declaration should not have the TypeVariableResolutionCapability? Is this ok?" +660,"@@ -32,8 +32,8 @@ public class EeaSendRawTransaction extends PrivacySendTransaction { + + public EeaSendRawTransaction( + final PrivacyParameters privacyParameters, +- final PrivateTransactionHandler privateTransactionHandler, +- final TransactionPool transactionPool) { ++ final TransactionPool transactionPool, ++ final PrivateTransactionHandler privateTransactionHandler) { + super(privacyParameters, privateTransactionHandler, transactionPool); + } + ",nit: any reason you swapped the ordering? +661,"@@ -4,7 +4,7 @@ define([""jQuery"", ""loading"", ""globalize"", ""dom""], function($, loading, globalize + function loadPage(page, config, systemInfo) { + Array.prototype.forEach.call(page.querySelectorAll("".chkDecodeCodec""), function(c) { + c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute(""data-codec"")) +- }), page.querySelector(""#chkHardwareEncoding"").checked = config.EnableHardwareEncoding, $(""#selectVideoDecoder"", page).val(config.HardwareAccelerationType), $(""#selectThreadCount"", page).val(config.EncodingThreadCount), $(""#txtDownMixAudioBoost"", page).val(config.DownMixAudioBoost), page.querySelector("".txtEncoderPath"").value = config.EncoderAppPath || """", $(""#txtTranscodingTempPath"", page).val(config.TranscodingTempPath || """"), $(""#txtVaapiDevice"", page).val(config.VaapiDevice || """"), page.querySelector(""#selectH264Preset"").value = config.H264Preset || """", page.querySelector(""#txtH264Crf"").value = config.H264Crf || """", page.querySelector(""#chkEnableSubtitleExtraction"").checked = config.EnableSubtitleExtraction || !1, page.querySelector(""#selectVideoDecoder"").dispatchEvent(new CustomEvent(""change"", { ++ }), page.querySelector(""#chkHardwareEncoding"").checked = config.EnableHardwareEncoding, $(""#selectVideoDecoder"", page).val(config.HardwareAccelerationType), $(""#selectThreadCount"", page).val(config.EncodingThreadCount), $(""#txtDownMixAudioBoost"", page).val(config.DownMixAudioBoost), page.querySelector("".txtEncoderPath"").value = config.EncoderAppPathDisplay || """", $(""#txtTranscodingTempPath"", page).val(config.TranscodingTempPath || """"), $(""#txtVaapiDevice"", page).val(config.VaapiDevice || """"), page.querySelector(""#selectH264Preset"").value = config.H264Preset || """", page.querySelector(""#txtH264Crf"").value = config.H264Crf || """", page.querySelector(""#chkEnableSubtitleExtraction"").checked = config.EnableSubtitleExtraction || !1, page.querySelector(""#selectVideoDecoder"").dispatchEvent(new CustomEvent(""change"", { + bubbles: !0 + })), loading.hide() + }",can you de-uglify at least this line?.. hard to tell what changed... +662,"@@ -354,13 +354,10 @@ type BPFDataplane interface { + RemoveXDP(ifName string, mode XDPMode) error + UpdateCIDRMap(ifName string, family IPFamily, ip net.IP, mask int, refCount uint32) error + UpdateFailsafeMap(proto uint8, port uint16) error +- loadXDPRaw(objPath, ifName string, mode XDPMode, mapArgs []string) error + GetBPFCalicoDir() string + AttachToSockmap() error + DetachFromSockmap(mode FindObjectMode) error + RemoveSockmap(mode FindObjectMode) error +- loadBPF(objPath, progPath, progType string, mapArgs []string) error +- LoadSockops(objPath string) error + LoadSockopsWithBytes(objBytes []byte) error + LoadSockopsAuto() error + RemoveSockops() error",Please can you merge master in before making these changes. I just reinstated a bunch of BPF UTs. Possible that the UTs use this code. +663,"@@ -66,3 +66,14 @@ class MyCls: + @classmethod + def get_class_var(cls): + return cls.__class_var ++ ++ ++class Bla: ++ """"""Regression test for issue 4638"""""" ++ ++ def __init__(self): ++ type(self).__a() ++ ++ @classmethod ++ def __a(cls): ++ pass",Do you want to add additional cases for `Bla.__b()` and `self.__c()`? (Just add additional classmethods `__b` and `__c` and the calls to `__init__`) +664,"@@ -462,7 +462,7 @@ def search(collection, p, of, ot, so, rm): + + ctx = dict( + facets=facets.get_facets_config(collection, qid), +- records=len(get_current_user_records_that_can_be_displayed(qid)), ++ records=len(recids), + qid=qid, rg=rg, + create_nearest_terms_box=lambda: _create_neareset_term_box(argd_orig), + easy_search_form=EasySearchForm(csrf_enabled=False),","the recids is never changed after. So, it should contains the exact shown results, whatever are the rights for the user (admin or simple user, restricted collections...)" +665,"@@ -669,7 +669,15 @@ func (b *Bucket) newRangeReader(ctx context.Context, key string, offset, length + + // WriteAll is a shortcut for creating a Writer via NewWriter and writing p. + func (b *Bucket) WriteAll(ctx context.Context, key string, p []byte, opts *WriterOptions) (err error) { +- w, err := b.NewWriter(ctx, key, opts) ++ realOpts := new(WriterOptions) ++ if opts != nil { ++ *realOpts = *opts ++ } ++ if len(realOpts.ContentMD5) == 0 { ++ sum := md5.Sum(p) ++ realOpts.ContentMD5 = sum[:] ++ } ++ w, err := b.NewWriter(ctx, key, realOpts) + if err != nil { + return err + }","Shouldn't the docstring mention that the MD5 checksum of `p` is computed each time and verified? Also, could there be use cases where a caller might not want such a check to happen because, eg, a blob storage solution doesn't provide MD5 verification or uses another hash algorithm such as SHA256?" +666,"@@ -143,6 +143,9 @@ def executeEvent(eventName,obj,**kwargs): + @param kwargs: Additional event parameters as keyword arguments. + """""" + try: ++ # Allow NVDAObjects to redirect focus events to another object of their choosing. ++ if eventName==""gainFocus"" and obj.focusRedirect: ++ obj=obj.focusRedirect + sleepMode=obj.sleepMode + if eventName==""gainFocus"" and not doPreGainFocus(obj,sleepMode=sleepMode): + return","focusRedirect is used in the powerpnt appModule. We might have to make sure that this does not break. Having said that, I really like this being handled on the events level!" +667,"@@ -21,6 +21,8 @@ import ( + ""encoding/base64"" + ""encoding/json"" + ""fmt"" ++ ""github.com/GoogleCloudPlatform/compute-image-tools/osconfig_tests/config"" ++ ""github.com/GoogleCloudPlatform/compute-image-tools/osconfig_tests/gcp_clients"" + ""io"" + ""log"" + ""path""",You imports are out of order +668,"@@ -45,7 +45,7 @@ import org.slf4j.LoggerFactory; + public class QuartzScheduler { + + //Unless specified, all Quartz jobs's identities comes with the default job name. +- private static final String DEFAULT_JOB_NAME = ""job1""; ++ public static final String DEFAULT_JOB_NAME = ""job1""; + private static final Logger logger = LoggerFactory.getLogger(QuartzScheduler.class); + private Scheduler scheduler = null; + ","This should not be called Flow Trigger. FlowTrigger should has its own flowTrigger job name, for instance, ""flowtrigger""" +669,"@@ -0,0 +1,19 @@ ++// Copyright (c) 2018 IoTeX ++// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no ++// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent ++// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache ++// License 2.0 that can be found in the LICENSE file. ++ ++package sqlite3 ++ ++import ( ++ ""github.com/iotexproject/iotex-core/config"" ++ ""github.com/iotexproject/iotex-core/db"" ++ // this is required for sqlite3 usage ++ _ ""github.com/mattn/go-sqlite3"" ++) ++ ++// NewSQLite3 instantiates an sqlite3 ++func NewSQLite3(cfg *config.SQLITE3) db.Store { ++ return db.NewSQLBase(""sqlite3"", cfg.SQLite3File) ++}",File is not `goimports`-ed (from `goimports`) +670,"@@ -30,6 +30,10 @@ public partial class Program + + public static void Stress(int concurrency = 0) + { ++#if DEBUG ++ Console.WriteLine(""***WARNING*** The current build is DEBUG which may affect timing!\n""); ++#endif ++ + if (concurrency < 0) + { + throw new ArgumentOutOfRangeException(nameof(concurrency), ""concurrency level should be a non-negative number."");",Why do we need `\n` if we already use `WriteLine`? (and `\n` is not cross platform) +671,"@@ -30,12 +30,15 @@ import com.google.common.base.MoreObjects; + public class MetricsConfiguration { + private static final String DEFAULT_METRICS_HOST = ""127.0.0.1""; + public static final int DEFAULT_METRICS_PORT = 9545; +- ++ private static final String DEFAULT_INSTRUMENTATION_NAME = ""besu""; ++ private static final String DEFAULT_METRICS_PROTOCOL = ""prometheus""; + private static final String DEFAULT_METRICS_PUSH_HOST = ""127.0.0.1""; + public static final int DEFAULT_METRICS_PUSH_PORT = 9001; + public static final Boolean DEFAULT_TIMERS_ENABLED = true; + + private final boolean enabled; ++ private final String instrumentationName; ++ private final String protocol; + private final int port; + private int actualPort; + private final String host;","What is instrumentation name used for? I'm not seeing other classes use it, only a getter, constructor, and builder." +672,"@@ -21,8 +21,10 @@ namespace Nethermind.TxPool.Collections + { + public partial class SortedPool + { ++#pragma warning disable 67 + public event EventHandler? Inserted; + public event EventHandler? Removed; ++#pragma warning restore 67 + + public class SortedPoolEventArgs + {",@kristofgazso could you review these warnings? +673,"@@ -0,0 +1,3 @@ ++require(""child_process""); ++ ++console.log(""hi"");",will delete this. +674,"@@ -104,9 +104,9 @@ module PurchasesHelper + + def new_plan_link(plan) + link_to( +- I18n.t('subscriptions.choose_plan_html', plan_name: plan.name).html_safe, +- new_individual_plan_purchase_path(plan), +- class: 'button' ++ I18n.t('subscriptions.choose_plan_html', plan_name: plan.name).html_safe, ++ new_individual_plan_purchase_path(plan), ++ class: 'button' + ) + end + end",~~Indent 2 lines above~~ Disregard. My fault +675,"@@ -366,7 +366,7 @@ public class InitCodeTransformer { + default: + throw new UnsupportedOperationException(""unexpected entity name type""); + } +- } else if (initValueConfig.hasFormattingConfig()) { ++ } else if (initValueConfig.hasFormattingConfig() && !item.getType().isRepeated()) { + if (context.getFeatureConfig().enableStringFormatFunctions()) { + FormattedInitValueView.Builder initValue = FormattedInitValueView.newBuilder(); + ",What was the bug that this is fixing? +676,"@@ -471,6 +471,9 @@ class RemoteConnection(object): + request.add_header('Accept', 'application/json') + request.add_header('Content-Type', 'application/json;charset=UTF-8') + ++ base64string = base64.b64encode('%s:%s' % (parsed_url.username, parsed_url.password)) ++ request.add_header(""Authorization"", ""Basic %s"" % base64string) ++ + if password_manager: + opener = url_request.build_opener(url_request.HTTPRedirectHandler(), + HttpErrorHandler(),","This will always add the authorization header to the request object. Is this the right scope for these two lines? If username/password are not defined, it will encode 'Basic :'" +677,"@@ -50,7 +50,12 @@ uint32_t lcg_rand() { + } + void lcg_reset() { lcg_seed = 48271; } + +-std::string test_data_path = ""tests/""; ++std::string test_data_path = ++#ifdef BAZEL_TEST_DATA_PATH ++ ""../com_github_google_flatbuffers/tests/""; ++#else ++ ""tests/""; ++#endif + + // example of how to build up a serialized buffer algorithmically: + flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {",Is this always how Bazel does paths? Would it be nicer to do `-DBAZEL_TEST_DATA_PATH=../com_github_google_flatbuffers/tests/` so this string is not hardcoded in the the source? +678,"@@ -169,7 +169,9 @@ class ElasticsearchTarget(luigi.Target): + + The document id would be sufficient but, + for documentation, +- we index the parameters `update_id`, `target_index`, `target_doc_type` and `date` as well. ++ we index the parameters `update_id`, `target_index`, `target_doc_type` and `date` as well. `date_utc` added ++ so we can be sure to get the actual date and time based upon UTC and not the client date and time based on the ++ client machine. + """""" + self.create_marker_index() + self.es.index(index=self.marker_index, doc_type=self.marker_doc_type,","Not an expert of ES, so not sure of the impact here." +679,"@@ -1665,10 +1665,10 @@ NABoolean ExExeUtilGetMetadataInfoTcb::checkUserPrivs( + if (ComUser::isRootUserID()) + return FALSE; + +- // any user granted the DB__ROOTROLE sees everything + Int32 numRoles; + Int32 *roleList; +- if (currContext->getRoleList(numRoles, roleList) == SUCCESS) ++ Int32 *granteeList; ++ if (currContext->getRoleList(numRoles, roleList, granteeList) == SUCCESS) + { + char authIDAsChar[sizeof(Int32)+10]; + NAString auths;",Who deletes the memory for the granteeList? (or the roleList for that matter) +680,"@@ -13,6 +13,11 @@ ws_listener (listener_a), ws (std::move (socket_a)), write_strand (ws.get_execut + + nano::websocket::session::~session () + { ++ for (auto & subscription : subscriptions) ++ { ++ ws_listener.decrease_subscription_count (subscription); ++ } ++ + ws_listener.get_node ().logger.try_log (""websocket session ended""); + } + ",This loop is missing a lock on subscriptions_mutex. +681,"@@ -62,7 +62,9 @@ Workshops::Application.routes.draw do + match '/backbone-js-on-rails' => redirect(""/products/1-backbone-js-on-rails"") + + match '/rubyist-booster-shot' => ""high_voltage/pages#show"", as: :rubyist_booster_shot, id: ""rubyist-booster-shot"" +- match 'sign_in' => 'sessions#new', as: 'sign_in' ++ match '/sign_up' => 'users#new', as: 'sign_up' ++ match '/sign_in' => 'sessions#new', as: 'sign_in' ++ match '/sign_out' => 'sessions#destroy', as: 'sign_out', via: :delete + + mount Split::Dashboard, at: 'split' + ",shouldn't clearance be setting these up for us? +682,"@@ -46,6 +46,10 @@ type ( + } + + defaultServiceNameDetector struct{} ++ ++ // noOp is a Detector that only provides an empty resource. Used ++ // to disable automatic detection. ++ noOp struct{} + ) + + var (",Need to update the doc for `TelemetrySDK` and `Host` structs deleting references from removed functions. +683,"@@ -55,12 +55,6 @@ public final class ASTRecordDeclaration extends AbstractAnyTypeDeclaration { + return isNested() || isLocal(); + } + +- @Override +- public boolean isFinal() { +- // A record is implicitly final +- return true; +- } +- + @Override + public boolean isLocal() { + return getParent() instanceof ASTBlockStatement;",I think we should keep that here and add a new method `isSyntacticallyFinal` that returns `super.isFinal()` (and can be used in UnnecessaryModifier). Otherwise the contract of `isFinal` is not respected +684,"@@ -2444,6 +2444,11 @@ angular.module('ui.grid') + // to get the full position we need + scrollPixels = self.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow); + ++ //Since scrollIfNecessary is called multiple times when enableCellEditOnFocus is true we need to make sure the scrollbarWidth and footerHeight is accounted for to not cause a loop. ++ if (gridCol.colDef.enableCellEditOnFocus === true) { ++ scrollPixels = scrollPixels - self.footerHeight - self.scrollbarWidth; ++ } ++ + scrollEvent.y = getScrollY(scrollPixels, scrollLength, self.renderContainers.body.prevScrolltopPercentage); + } + // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...",Is there a reason why we wouldn't want to check this every time? Why are we only checking for the footer and scroll bar when enableCellEditOnFocus is true? +685,"@@ -23,6 +23,7 @@ import com.playonlinux.common.dtos.*; + import com.playonlinux.domain.PlayOnLinuxError; + import com.playonlinux.injection.Scan; + import com.playonlinux.injection.Inject; ++import com.playonlinux.ui.api.InstallerFilter; + import com.playonlinux.webservice.RemoteAvailableInstallers; + + import java.net.MalformedURLException;",You need to create an API for this class. This class should follow roughly the same dependency structure than RemoteAvailableInstallersPlayOnLinuxImplementation / RemoteAvailableInstallers. Maybe we could use a inner class here? +686,"@@ -42,7 +42,7 @@ const ( + templateCreateWorkflowExecutionClosed = `INSERT INTO executions_visibility (` + + `namespace_id, workflow_id, run_id, start_time, execution_time, workflow_type_name, close_time, status, history_length, memo, encoding) ` + + `VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ` + +- `ON DUPLICATE KEY UPDATE start_time = VALUES(start_time), execution_time = VALUES(execution_time), workflow_type_name = VALUES(workflow_type_name), ` + ++ `ON DUPLICATE KEY UPDATE workflow_id = VALUES(workflow_id), start_time = VALUES(start_time), execution_time = VALUES(execution_time), workflow_type_name = VALUES(workflow_type_name), ` + + `close_time = VALUES(close_time), status = VALUES(status), history_length = VALUES(history_length), memo = VALUES(memo), encoding = VALUES(encoding)` + + // RunID condition is needed for correct pagination","This should not be a case, right? If `run_id` is the same `workflow_id` can't be changed. Actually surprised that it is not part of a key." +687,"@@ -4520,7 +4520,9 @@ RelExpr * GenericUpdate::preCodeGen(Generator * generator, + { + oltOptInfo().setOltOpt(FALSE); + generator->oltOptInfo()->setOltOpt(FALSE); +- generator->setAqrEnabled(FALSE); ++ //enabling AQR to take care of the lock conflict error 8558 that ++ // should be retried. ++ // generator->setAqrEnabled(FALSE); + generator->setUpdAbortOnError(TRUE); + generator->setUpdSavepointOnError(FALSE); + }",How would AQR work for an INSERT/SELECT of one table into another where a LOB column is being copied? +688,"@@ -6,9 +6,11 @@ import ( + ""net"" + ""os"" + +- sds_v2 ""github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2"" ++ discovery_v2 ""github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2"" ++ secret_v3 ""github.com/envoyproxy/go-control-plane/envoy/service/secret/v3"" + attestor ""github.com/spiffe/spire/pkg/agent/attestor/workload"" +- ""github.com/spiffe/spire/pkg/agent/endpoints/sds"" ++ ""github.com/spiffe/spire/pkg/agent/endpoints/sds/sdsv2"" ++ ""github.com/spiffe/spire/pkg/agent/endpoints/sds/sdsv3"" + ""github.com/spiffe/spire/pkg/agent/endpoints/workload"" + ""github.com/spiffe/spire/pkg/common/peertracker"" + ""github.com/spiffe/spire/pkg/common/telemetry""","Since these are ultimately different endpoints, it would be nice if we could move them up one level and nuke the common `sds` directory in order to reduce path stutter" +689,"@@ -927,7 +927,7 @@ export default function Core(rootElement, userSettings, rootInstanceSymbol = fal + if (isFunction(beforeChangeResult)) { + warn('Your beforeChange callback returns a function. It\'s not supported since Handsontable 0.12.1 (and the returned function will not be executed).'); + +- } else if (beforeChangeResult === false) { ++ } else if (beforeChangeResult === false || beforeChangeResult.length === 0 || beforeChangeResult[0] === null) { + const activeEditor = instance.getActiveEditor(); + + if (activeEditor) {",Please check also whether `null` occurs in the rest of `beforeChangeResult` array. +690,"@@ -22,9 +22,10 @@ package transport + + import ""context"" + +-// Filter defines transport-level middleware for Outbounds. ++// UnaryFilter defines transport-level middleware for `UnaryOutbound`s. ++// Note: this is client side. + // +-// Filters MAY ++// UnaryFilter MAY + // + // - change the context + // - change the request","Outdated docs. There is no response, there's an ack." +691,"@@ -27,7 +27,7 @@ your host.`, + } + switch status { + case libcontainer.Created: +- return container.Signal(libcontainer.InitContinueSignal) ++ return container.Exec() + case libcontainer.Stopped: + return fmt.Errorf(""cannot start a container that has run and stopped"") + case libcontainer.Running:","I'd rather have the container process remove the FIFO after it unblocks. Then `start` can always `Exec()`, and you can catch the ""FIFO does not exist"" error and translate it to a prettier ""someone must have already started the container""." +692,"@@ -284,7 +284,7 @@ func (svr *Web3Server) getTransactionFromActionInfo(actInfo *iotexapi.ActionInfo + + func (svr *Web3Server) getTransactionCreateFromActionInfo(actInfo *iotexapi.ActionInfo) (transactionObject, error) { + tx, err := svr.getTransactionFromActionInfo(actInfo) +- if err != nil { ++ if err != nil || tx == nil { + return transactionObject{}, err + } + ",can you check if there's other similar cases to add nil-check like this? +693,"@@ -106,7 +106,10 @@ def dummy_cert(privkey, cacert, commonname, sans, organization): + cert.gmtime_adj_notBefore(-3600 * 48) + cert.gmtime_adj_notAfter(DEFAULT_EXP_DUMMY_CERT) + cert.set_issuer(cacert.get_subject()) +- if commonname is not None and len(commonname) < 64: ++ is_valid_commonname = ( ++ commonname is not None and len(commonname) < 64 ++ ) ++ if is_valid_commonname: + cert.get_subject().CN = commonname + if organization is not None: + cert.get_subject().O = organization","`<= 64`? I just picked up what you said in #3981 (""the CN field is limited to 64 characters"") but maybe there's something I don't know where the 64th character is needed (trailing dot or whatever?) Also this sounds like something that could be beautifully unit tested. Sorry for bugging you :grin:" +694,"@@ -20,4 +20,10 @@ class License < ActiveRecord::Base + def short_name + abbreviation.blank? ? nice_name : abbreviation + end ++ ++ class << self ++ def autocomplete(term) ++ License.select([:nice_name, :id]).where(['lower(nice_name) LIKE ?', ""#{term.downcase}%""]).limit(10) ++ end ++ end + end",I understand that this grabs a Licenses objects but what is the autocomplete method used for? What does this do in context of the auto_completes controller? +695,"@@ -480,6 +480,10 @@ public class BlockchainQueries { + txs.get(txIndex), header.getNumber(), blockHeaderHash, txIndex); + } + ++ public Optional transactionLocationByHash(final Hash transactionHash) { ++ return blockchain.getTransactionLocation(transactionHash); ++ } ++ + /** + * Returns the transaction receipt associated with the given transaction hash. + *",I don't really like that way of naming methods based on their arguments. But I can see that the other method names are the same ... +696,"@@ -180,6 +180,19 @@ public class StringUtil { + } + } + ++ public static String sanitizeFileDirectory(String value){ ++ ++ while (value.startsWith(""\\"") || value.startsWith(""/"") || value.startsWith(""-"") || value.startsWith(""."")){ ++ value = value.substring(1); ++ } ++ while (value.endsWith(""\\"") || value.endsWith(""/"") || value.endsWith(""-"") || value.endsWith(""."")){ ++ value = value.substring(0, value.length() - 1); ++ } ++ ++ return value; ++ } ++ ++ + private static SecretKeySpec generateKeyFromString(final String secKey) throws UnsupportedEncodingException, NoSuchAlgorithmException { + byte[] key = (secKey).getBytes(""UTF-8""); + MessageDigest sha = MessageDigest.getInstance(""SHA-1"");","@sekmiller This method correctly strips the leading and trailing slashes (and also ""."" and ""-""); But I thought the plan was also to replace any multiple slashes between nested folders with a single slash. For example, as implemented now, I can enter ""folder1///folder2"", and it gets saved and displayed like this, with the 3 slashes. I thought we wanted to sanitize it as ""folder1/folder2""." +697,"@@ -45,7 +45,7 @@ + + int main() + { +- int pid; ++ int64_t pid; + fprintf(stderr, ""starting\n""); + #if defined(AARCH64) + asm(""movz x8, "" STRINGIFY(SYS_getpid) "";""",Looks like the X86 inline assembly is not happy with this type. I will update that +698,"@@ -6,6 +6,12 @@ + +

<%= link_to h(diary_entry.title), :action => 'view', :display_name => diary_entry.user.display_name, :id => diary_entry.id %>

+ ++ <% if @user and diary_entry.user.id != @user.id %> ++ <%= link_to new_issue_url(reportable_id: diary_entry.id, reportable_type: diary_entry.class.name, reported_user_id: diary_entry.user.id,referer: request.fullpath), :title => t('diary_entry.diary_entry.report') do %> ++  ⚐ ++ <% end %> ++ <% end %> ++ + + <%= raw(t 'diary_entry.diary_entry.posted_by', :link_user => (link_to h(diary_entry.user.display_name), :controller => 'user', :action => 'view', :display_name => diary_entry.user.display_name), :created => l(diary_entry.created_at, :format => :blog), :language_link => (link_to h(diary_entry.language.name), :controller => 'diary_entry', :action => 'list', :display_name => nil, :language => diary_entry.language_code)) %> + ","Tabs and a space, again." +699,"@@ -2441,6 +2441,16 @@ bool QuestManager::istaskappropriate(int task) { + return false; + } + ++std::string QuestManager::gettaskname(uint32 task_id) { ++ QuestManagerCurrentQuestVars(); ++ ++ if (RuleB(TaskSystem, EnableTaskSystem)) { ++ return taskmanager->GetTaskName(task_id); ++ } ++ ++ return std::string(); ++} ++ + void QuestManager::clearspawntimers() { + if(!zone) + return;",Please just enclose if blocks with brackets; this has created issues in the past so I'd prefer we don't use them +700,"@@ -185,11 +185,7 @@ + <% if policy(@proposal).can_approve_or_reject? %> +
+

+- <%= link_to ""Approve"", +- approval_response_path(approver_action: 'approve', +- # @todo: get rid of cart +- cart_id: @proposal.cart.id, version: @proposal.version +- ), class: 'form-button' %> ++ <%= link_to ""Approve"", approve_proposal_url(@proposal, version: @proposal.version), class: 'form-button' %> +

+
+ <% end %>","`version` isn't need anymore because it's built into `approve_proposal_url`, yes?" +701,"@@ -11,9 +11,10 @@ import struct + + from scapy.compat import orb, chb + from scapy.config import conf +-from scapy.data import MTU, DLT_BLUETOOTH_LE_LL ++from scapy.data import MTU, DLT_BLUETOOTH_LE_LL, DLT_BLUETOOTH_LE_LL_WITH_PHDR + from scapy.packet import * + from scapy.fields import * ++from scapy.layers.dot11 import _dbmField + from scapy.layers.ppi import PPI, addPPIType, PPIGenericFldHdr + + from scapy.contrib.ppi_geotag import XLEIntField, XLEShortField",Moved to the bottom of the file. `CtrlPDU` sits on `BTLE_DATA` so let's put it after +702,"@@ -48,6 +48,7 @@ module Blacklight::SolrHelper + extend ActiveSupport::Concern + include Blacklight::SearchFields + include Blacklight::Facet ++ require 'json' + + included do + if self.respond_to?(:helper_method)","This ends up requiring the `json` gem, right? Is there any way we can do this to be implementation agnostic (e.g. to let me use `yajl-ruby` for performance reasons (or because my app already brings in a JSON library)" +703,"@@ -56,8 +56,13 @@ type byteReadCloser struct{ io.ReadCloser } + // ReadByte implements the io.ByteReader interface. + func (b byteReadCloser) ReadByte() (byte, error) { + var buf [1]byte +- _, err := b.Read(buf[:]) +- return buf[0], err ++ for { ++ n, err := b.Read(buf[:]) ++ if n == 0 && err == nil { ++ continue ++ } ++ return buf[0], err ++ } + } + + // A compressor builds a Riegeli compressed block.","This seems dangerous. What circumstances lead to the need for a retry? Can that happen more than once? I'm concerned that if we hit the pathological state, this could turn into a CPU spinner. I wonder if we could get the same benefit from just ""trying again"" and failing if it fails the second time." +704,"@@ -20,11 +20,18 @@ + package org.apache.iceberg; + + import java.util.List; ++import java.util.Optional; + import org.apache.iceberg.exceptions.ValidationException; + import org.apache.iceberg.expressions.Expressions; ++import org.apache.iceberg.util.PartitionSet; + + public class BaseReplacePartitions + extends MergingSnapshotProducer implements ReplacePartitions { ++ ++ private final PartitionSet deletedPartitions = PartitionSet.create(super.getSpecsById()); ++ private Long startingSnapshotId = null; ++ private boolean validateNoConflictingAppends = false; ++ + BaseReplacePartitions(String tableName, TableOperations ops) { + super(tableName, ops); + set(SnapshotSummary.REPLACE_PARTITIONS_PROP, ""true"");","If there is a reference to other fields or methods, please do the initialization in the constructor." +705,"@@ -0,0 +1,13 @@ ++// This object is imported into the documentation site. An example for the documentation site should be part of the pull request for the component. The object key is the kabob case of the ""URL folder"". In the case of `http://localhost:8080/components/app-launcher/`, `app-launcher` is the `key`. The folder name is created by `components.component` value in `package.json`. The following uses webpack's raw-loader plugin to get ""text files"" that will be eval()'d by CodeMirror within the documentation site on page load. ++ ++/* eslint-env node */ ++/* eslint-disable global-require */ ++ ++const siteStories = [ ++ require('raw-loader!@salesforce/design-system-react/components/pill/__examples__/base.jsx'), ++ require('raw-loader!@salesforce/design-system-react/components/pill/__examples__/icons.jsx'), ++ require('raw-loader!@salesforce/design-system-react/components/pill/__examples__/avatars.jsx'), ++ require('raw-loader!@salesforce/design-system-react/components/pill/__examples__/bare.jsx'), ++]; ++ ++module.exports = siteStories;",These should be importing from `pill-container` +706,"@@ -2593,12 +2593,12 @@ void Game::playerRequestTrade(uint32_t playerId, const Position& pos, uint8_t st + + Player* tradePartner = getPlayerByID(tradePlayerId); + if (!tradePartner || tradePartner == player) { +- player->sendTextMessage(MESSAGE_INFO_DESCR, ""Sorry, not possible.""); ++ player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return; + } + + if (!Position::areInRange<2, 2, 0>(tradePartner->getPosition(), player->getPosition())) { +- player->sendTextMessage(MESSAGE_INFO_DESCR, fmt::format(""{:s} tells you to move closer."", tradePartner->getName())); ++ player->sendCancelMessage(RETURNVALUE_DESTINATIONOUTOFREACH); + return; + } + ","Why this change? It will now only show on the bottom of the screen as white text, is it correct behaviour?" +707,"@@ -46,7 +46,7 @@ module Blacklight + + fields = Array.wrap(view_config.title_field) + [configuration.document_model.unique_key] + f = fields.lazy.map { |field| field_config(field) }.detect { |field_config| field_presenter(field_config).any? } +- field_value(f, except_operations: [Rendering::HelperMethod]) ++ f ? field_value(f, except_operations: [Rendering::HelperMethod]) : """" + end + + def display_type(base_name = nil, default: nil)",Does this need to allocate a string or would a nil value (indicating no header) be a better? +708,"@@ -13,6 +13,7 @@ import { Fragment } from './create-element'; + export function Component(props, context) { + this.props = props; + this.context = context; ++ // this.constructor // When component is functional component, this is reseted to functional component + // if (this.state==null) this.state = {}; + // this.state = {}; + // this._dirty = true;",Nit: Past tense of `reset` is also `reset`. +709,"@@ -672,6 +672,12 @@ class Commands: + """""" return wallet synchronization status """""" + return self.wallet.is_up_to_date() + ++ @command('') ++ def getfee(self): ++ """"""Return current optimal fee per kilobyte, according to ++ config settings (static/dynamic)"""""" ++ return self.config.fee_per_kb() ++ + @command('') + def help(self): + # for the python console",Shouldn't this use `'n'` instead? +710,"@@ -451,10 +451,10 @@ func (t *timerQueueProcessorBase) getTimerTaskType( + switch taskType { + case enumsspb.TASK_TYPE_USER_TIMER: + return ""UserTimer"" +- case enumsspb.TASK_TYPE_ACTIVITY_TIMEOUT: +- return ""ActivityTimeout"" +- case enumsspb.TASK_TYPE_DECISION_TIMEOUT: +- return ""DecisionTimeout"" ++ case enumsspb.TASK_TYPE_ACTIVITY_TASK_TIMEOUT: ++ return ""ActivityTaskTimeout"" ++ case enumsspb.TASK_TYPE_WORKFLOW_TASK_TIMEOUT: ++ return ""WorkflowTaskTimeout"" + case enumsspb.TASK_TYPE_WORKFLOW_RUN_TIMEOUT: + return ""WorkflowRunTimeout"" + case enumsspb.TASK_TYPE_DELETE_HISTORY_EVENT:",revert back to 'TASK_TYPE_ACTIVITY_TIMEOUT' +711,"@@ -105,6 +105,9 @@ Engine::Engine(core::Engine *engine) : m_Engine(engine) {} + template void Engine::Get(const std::string &, std::vector &, \ + const Mode); \ + \ ++ template void Engine::GetBlock(Variable, T **, const Mode); \ ++ template void Engine::GetBlock(const std::string &, T **, const Mode); \ ++ \ + template std::map::Info>> \ + Engine::AllStepsBlocksInfo(const Variable variable) const; \ + \","Shouldn't we prefer passing a pointer by reference T*&, since these are C++ bindings?" +712,"@@ -146,9 +146,15 @@ func (n *NetworkPolicyController) processClusterNetworkPolicy(cnp *secv1alpha1.C + appliedToGroupNamesForRule = append(appliedToGroupNamesForRule, atGroup) + appliedToGroupNamesSet.Insert(atGroup) + } ++ cgExists := len(ingressRule.SourceGroups) > 0 ++ iFromPeers := n.toAntreaPeerForCRD(ingressRule.From, cnp, controlplane.DirectionIn, namedPortExists, cgExists) ++ // If ClusterGroups are set in Rule, then create AddressGroups corresponding to the CG and append to From Peers. ++ ag, ipb := n.processRefCGs(ingressRule.SourceGroups) ++ iFromPeers.IPBlocks = append(iFromPeers.IPBlocks, ipb...) ++ iFromPeers.AddressGroups = append(iFromPeers.AddressGroups, ag...) + rules = append(rules, controlplane.NetworkPolicyRule{ + Direction: controlplane.DirectionIn, +- From: *n.toAntreaPeerForCRD(ingressRule.From, cnp, controlplane.DirectionIn, namedPortExists), ++ From: iFromPeers, + Services: services, + Action: ingressRule.Action, + Priority: int32(idx),",nit: Personally I feel that it's cleaner to let `toAntreaPeerForCRD` to take `ingressRule` as a param instead of `ingressRule.From`. It can call `processRefCGs` inside the function and do the ipBlock/AG union within the function itself. It might not be worth the refactor though. +713,"@@ -98,6 +98,7 @@ func updateSPCVersion(name string) error { + return err + } + spcObj.VersionDetails.Desired = upgradeVersion ++ spcObj.VersionDetails.Status.State = apis.ReconcilePending + _, err = client.Update(spcObj) + if err != nil { + return err","Pending has been set only for SPC.. why? for other CRs as well, this need to be done.. right?" +714,"@@ -61,11 +61,13 @@ class VimeoProvider extends BaseVideoProvider + $box = $this->getBoxHelperProperties($media, $format, $options); + + $params = array( +- 'src' => http_build_query($player_parameters), +- 'id' => $player_parameters['js_swf_id'], +- 'frameborder' => isset($options['frameborder']) ? $options['frameborder'] : 0, +- 'width' => $box->getWidth(), +- 'height' => $box->getHeight(), ++ 'src' => http_build_query($player_parameters), ++ 'id' => $player_parameters['js_swf_id'], ++ 'frameborder' => isset($options['frameborder']) ? $options['frameborder'] : 0, ++ 'width' => $box->getWidth(), ++ 'height' => $box->getHeight(), ++ 'class' => isset($options['class']) ? $options['class'] : '', ++ 'allow_fullscreen' => isset($options['allowfullscreen']) ? true : false, + ); + + return $params;",would use an empty string here as default and then check for emptiness in the twig template. I dont like mixing types @core23 what do you think? +715,"@@ -169,6 +169,8 @@ public class PhpSampleMethodToViewTransformer implements SampleMethodToViewTrans + builder.isResourceMap(fieldInfo.type().isMap()); + builder.pageVarName( + symbolTable.getNewSymbol(namer.localVarName(Name.lowerCamel(fieldInfo.name())))); ++ builder.pageTokenName(methodInfo.requestPageTokenName()); ++ builder.nextPageTokenName(Name.lowerCamel(methodInfo.responsePageTokenName()).toUpperCamel()); + return builder.build(); + } + }",How come we need case manipulation for the nextPageToken and not for pageToken? +716,"@@ -2,7 +2,8 @@ C2::Application.routes.draw do + ActiveAdmin.routes(self) + root :to => 'home#index' + get '/error' => 'home#error' +- get '/me' => 'home#me' ++ get '/me' => 'profile#show' ++ post '/me' => 'profile#update' + get '/feedback' => 'feedback#index' + get '/feedback/thanks' => 'feedback#thanks' + post '/feedback' => 'feedback#create'",why use these rather than regular named paths? +717,"@@ -61,6 +61,9 @@ module Bolt + { flags: OPTIONS[:global], + banner: GROUP_HELP } + end ++ when 'guide' ++ { flags: OPTIONS[:global] + %w[format], ++ banner: GUIDE_HELP } + when 'plan' + case action + when 'convert'","Hm, I don't think the extra flags are doing any harm here, but it does seem like `--help` is the only flag you could *actually* use with this command. We might eventually want to separate those out." +718,"@@ -1,3 +1,18 @@ ++# This script is responsible to create candidate sets for all users. The generated candidate sets ++# will be given as input to the recommender to assign ratings to the recordings in candidate sets. ++# The general flow is as follows: ++# ++# Last 7 days listens are filtered from mapped_listens_df and is called the mapped_listens_subset_df. ++# Top X artists are fetched for each user from the mapped_listens_subset_df. The top_artist_df is joined ++# with recordings_df to get the dataframe of recordings belonging to the top artists. From this dataframe, ++# recordings listened to by the users in the last 7 days are filtered so that the recommendations don't contain ++# recordings that the user has listened to in the last week. The resultant dataframe is called the top_artists_candidate_set_df. ++# ++# Artists similar to top artists are fetched from the artist_relations_df and the similar_artist_candidate_set_df is generated ++# in a manner similar to the generation of the top artist candidate set. ++# ++# The top artist and similar artist candidate set dataframes are saved to HDFS. ++ + import os + import sys + import uuid","We should make this a docstring, so that editors are able to pick it up." +719,"@@ -14,5 +14,13 @@ feature ""User without a subscription views sample video"" do + expect(current_path).to eq(video_path(video)) + expect(page).to have_css(""h1"", text: video.name) + expect(page).not_to have_css("".locked-message"") ++ expect_authed_to_access_event_fired_for(video) ++ end ++ ++ def expect_authed_to_access_event_fired_for(video) ++ expect(analytics).to have_tracked(""Authed to Access"").with_properties( ++ video_name: video.name, ++ watchable_name: video.watchable_name, ++ ) + end + end",Put a comma after the last parameter of a multiline method call. +720,"@@ -150,10 +150,8 @@ public class SalesforceDroidGapActivity extends CordovaActivity { + webSettings.setDomStorageEnabled(true); + String cachePath = getApplicationContext().getCacheDir().getAbsolutePath(); + webSettings.setAppCachePath(cachePath); +- webSettings.setAppCacheMaxSize(1024 * 1024 * 8); + webSettings.setAppCacheEnabled(true); + webSettings.setAllowFileAccess(true); +- webSettings.setSavePassword(false); + webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); + EventsObservable.get().notifyEvent(EventType.GapWebViewCreateComplete, appView); + }",App cache size is now managed dynamically by the `WebView`. This statement has no effect in the new framework. +721,"@@ -1,4 +1,6 @@ +-var nn = node.nodeName.toLowerCase(); +-return ( +- node.hasAttribute('alt') && (nn === 'img' || nn === 'input' || nn === 'area') +-); ++const { nodeName } = virtualNode.props; ++if (['img', 'input', 'area'].includes(nodeName) === false) { ++ return false; ++} ++ ++return typeof virtualNode.attr('alt') === 'string';","VirtualNode has a `hasAttr` function, any reason why you're not using it?" +722,"@@ -69,7 +69,6 @@ public class HttpAccess { + * Initializes HttpAccess. Should be called from the application. + */ + public static void init(Context app) { +- assert DEFAULT == null : ""HttpAccess.init should be called once per process""; + DEFAULT = new HttpAccess(app, null /* user agent will be calculated at request time */); + } + ",This now throws when running tests (maybe the move to java 11??). Do we want to keep it? +723,"@@ -45,8 +45,8 @@ func EncodeSha1(str string) string { + } + + func ShortSha(sha1 string) string { +- if len(sha1) == 40 { +- return sha1[:10] ++ if len(sha1) > 7 { ++ return sha1[:7] + } + return sha1 + }","We can allow 7-char SHA, does not mean we want to show with 7-char in default, please change to `if len() > 10`, then cut." +724,"@@ -66,8 +66,10 @@ en_US.strings = { + loading: 'Loading...', + logOut: 'Log out', + myDevice: 'My Device', ++ noDuplicates: 'Cannot add the duplicate file %{fileName}, it already exists', + noFilesFound: 'You have no files or folders here', + noInternetConnection: 'No Internet connection', ++ noNewAlreadyUploading: 'Cannot add new files: already uploading', + openFolderNamed: 'Open folder %{name}', + pause: 'Pause', + pauseUpload: 'Pause upload',",this one should also have quotes i guess :) +725,"@@ -106,12 +106,14 @@ func TestBuilderForYAML(t *testing.T) { + ""Test 2"": {fakeInvalidK8sResource, """", true}, + } + for name, mock := range tests { ++ name := name // pin it ++ mock := mock // pin it + t.Run(name, func(t *testing.T) { + b := BuilderForYaml(mock.resourceYAML) + if mock.expectError && len(b.errs) == 0 { + t.Fatalf(""Test %s failed, expected err but got 0"", name) +- } else if b.unstruct.object.GetName() != mock.expectedName { +- t.Fatalf(""Test %s failed, expected %v but got %v"", name, mock.expectedName, b.unstruct.object.GetName()) ++ } else if b.unstruct.Object.GetName() != mock.expectedName { ++ t.Fatalf(""Test %s failed, expected %v but got %v"", name, mock.expectedName, b.unstruct.Object.GetName()) + } + }) + }",Using the variable on range scope `mock` in function literal (from `scopelint`) +726,"@@ -1020,7 +1020,7 @@ public class Datasets extends AbstractApiBean { + PublishDatasetResult res = execCommand(new PublishDatasetCommand(ds, + createDataverseRequest(user), + isMinor)); +- return res.isCompleted() ? ok(json(res.getDataset())) : accepted(json(res.getDataset())); ++ return res.isWorkflow() ? accepted(json(res.getDataset())) : ok(json(res.getDataset())); + } + } catch (WrappedResponse ex) { + return ex.getResponse();",does this result in a 200 when the dataset is still inprogress/publishing not yet finalized? Seems like 202 is the right code for that (as it was) and the test should be watching for a 202? +727,"@@ -65,6 +65,7 @@ public class SmartStorePlugin extends ForcePlugin { + public static final String LIKE_KEY = ""likeKey""; + public static final String MATCH_KEY = ""matchKey""; + public static final String SMART_SQL = ""smartSql""; ++ public static final String ORDER_PATH = ""orderPath""; + public static final String ORDER = ""order""; + public static final String PAGE_SIZE = ""pageSize""; + public static final String QUERY_TYPE = ""queryType"";","Previously you could only order by the field you were searching by. But for full-text search, you can search across all indexed fields, and it didn't make sense not to have a sorting. For backward compatibility, the javascript code uses indexPath as the orderPath when no orderPath is provided." +728,"@@ -38,7 +38,7 @@ export function flushMounts() { + * Apply differences in a given vnode (and it's deep children) to a real DOM Node. + * @param {import('../dom').PreactElement} dom A DOM node to mutate into the shape of a `vnode` + * @param {import('../vnode').VNode} vnode A VNode (with descendants forming a tree) representing +- * the desired DOM structure ++ * the desired DOM structure + * @param {object} context The current context + * @param {boolean} mountAll Whether or not to immediately mount all components + * @param {Element} parent ?",VIM didn't like your whitespace. +729,"@@ -3,14 +3,7 @@ + // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. + // + +-using System; +-using System.Collections.Generic; +-using System.IO; +-using System.Linq; +-using System.Reflection; +-using System.Threading; +-using System.Threading.Tasks; +-using Datadog.Trace.TestHelpers; ++using Datadog.Trace.ClrProfiler; + using Xunit; + using Xunit.Abstractions; + using Xunit.Sdk;",Are you sure the namespace should change? +730,"@@ -12,7 +12,7 @@ namespace MvvmCross.ViewModels + + void Initialize(); + +- void Startup(object hint); ++ object Startup(object hint); + + void Reset(); + }",@martijn00 I'm not sure why we're keeping the object parameter and return type since this can be done by using MvxApplication with THint set to object +731,"@@ -31,6 +31,7 @@ import com.pingcap.tikv.meta.TiColumnInfo.InternalTypeHolder; + // https://dev.mysql.com/doc/refman/8.0/en/time.html + + public class TimeType extends DataType { ++ public static final TimeType TIME = new TimeType(MySQLType.TypeDuration); + public static final MySQLType[] subTypes = new MySQLType[] {MySQLType.TypeDuration}; + protected static final long NANOSECOND = 1; + protected static final long MICROSECOND = 1000 * NANOSECOND;",why do we create a time type here? +732,"@@ -1,4 +1,4 @@ +-define([""jQuery"", ""datetime"", ""loading"", ""libraryMenu"", ""listViewStyle"", ""paper-icon-button-light""], function ($, datetime, loading, libraryMenu) { ++define([""jQuery"", ""datetime"", ""loading"", ""libraryMenu"", ""css!components/listview/listview"", ""paper-icon-button-light""], function ($, datetime, loading, libraryMenu) { + ""use strict""; + + function populateRatings(allParentalRatings, page) {",Does this style actually need to get loaded in all of these components? +733,"@@ -30,6 +30,9 @@ import io.servicecomb.foundation.ssl.SSLCustom; + import io.servicecomb.foundation.ssl.SSLOption; + import io.servicecomb.foundation.ssl.SSLOptionFactory; + import io.servicecomb.foundation.vertx.VertxTLSBuilder; ++import io.servicecomb.transport.rest.vertx.accesslog.AccessLogConfiguration; ++import io.servicecomb.transport.rest.vertx.accesslog.impl.AccessLogHandlerImpl; ++import io.servicecomb.transport.rest.vertx.accesslog.parser.impl.DefaultAccessLogPatternParser; + import io.vertx.core.AbstractVerticle; + import io.vertx.core.Context; + import io.vertx.core.Future;",import but not used so you did not resolve compile warnings? +734,"@@ -865,15 +865,10 @@ BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int3 + } + + if (checkArmor) { +- int32_t armorValue = getArmor(); +- if (armorValue > 1) { +- double armorFormula = armorValue * 0.475; +- int32_t armorReduction = static_cast(std::ceil(armorFormula)); +- damage -= uniform_random( +- armorReduction, +- armorReduction + static_cast(std::floor(armorFormula)) +- ); +- } else if (armorValue == 1) { ++ int32_t armor = getArmor(); ++ if (armor > 3) { ++ damage -= uniform_random(armor / 2, armor - (armor % 2 + 1)); ++ } else if (armor > 0) { + --damage; + } + ",This is so much more concise and beautiful than the previous formula +735,"@@ -41,9 +41,19 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.PermissioningT + import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyTransactions; + import org.hyperledger.besu.tests.acceptance.dsl.transaction.web3.Web3Transactions; + ++import java.io.File; ++ ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import org.apache.logging.log4j.ThreadContext; + import org.junit.After; ++import org.junit.Rule; ++import org.junit.rules.TestName; ++import org.junit.rules.TestWatcher; ++import org.junit.runner.Description; + + public class AcceptanceTestBase { ++ protected final Logger LOG = LogManager.getLogger(); + + protected final Accounts accounts; + protected final AccountTransactions accountTransactions;",Is there any reason not to have the `static` modifier for the logger? _(that would be in keeping with the reference being uppercase)_ +736,"@@ -27,11 +27,18 @@ import ( + // DialogCreator creates new dialog between consumer and provider, using given contact information + type DialogCreator func(consumerID, providerID identity.Identity, contact market.Contact) (communication.Dialog, error) + ++// SessionCreationConfig are the parameters that get sent to the provider ++type SessionCreationConfig interface{} ++ ++// ConsumerConfig are the parameters used for the initiation of connection ++type ConsumerConfig interface{} ++ + // Connection represents a connection + type Connection interface { +- Start() error ++ Start(ConnectOptions) error + Wait() error + Stop() ++ GetSessionConfig() (SessionCreationConfig, error) + } + + // StateChannel is the channel we receive state change events on",It's not about session creation config. It's about passing consumer config parameters to underlying transport - nothing to do with session itself +737,"@@ -97,7 +97,7 @@ type ConfigLocal struct { + kbpki KBPKI + renamer ConflictRenamer + registry metrics.Registry +- loggerFn func(prefix string) logger.Logger ++ loggerFn func(prefix string, overrideEnableDebug bool) logger.Logger + noBGFlush bool // logic opposite so the default value is the common setting + rwpWaitTime time.Duration + diskLimiter DiskLimiter","Why is there an ""enable"" in the param name? Couldn't it just be `overrideDebug`? Here are everywhere else." +738,"@@ -1,4 +1,8 @@ + class VideosController < ApplicationController ++ def index ++ @videos = Video.published.recently_published_first ++ end ++ + def show + @video = Video.find(params[:id]) + @offering = Offering.new(@video.watchable, current_user)",`published.recently_published_first` reads a little oddly to me. Is this the same thing as `Video.published.ordered`? +739,"@@ -20,7 +20,11 @@ var createIntegrationPreprocessor = function(logger) { + // and add the test data to it + var htmlpath = file.originalPath.replace(extRegex, '.html'); + var html = fs.readFileSync(htmlpath, 'utf-8'); +- var test = JSON.parse(content); ++ try { ++ var test = JSON.parse(content); ++ } catch (e) { ++ throw new Error('Unable to parse content of ' + file.originalPath) ++ } + test.content = html; + + var result = template.replace('{}; /*tests*/', JSON.stringify(test));",Encountered this because I had a stray comma. Figured I'd tweak it a bit. +740,"@@ -306,6 +306,13 @@ var _ = infrastructure.DatastoreDescribe(""service loop prevention; with 2 nodes"" + cfg.Spec.ServiceLoopPrevention = ""Disabled"" + }) + ++ // Expect to see empty cali-cidr-block chains. (Allowing time for a Felix ++ // restart.) This ensures that the cali-cidr-block chain has been cleared ++ // before we try a test ping. ++ for _, felix := range felixes { ++ Eventually(getCIDRBlockRules(felix, ""iptables-save""), ""8s"", ""0.5s"").Should(BeEmpty()) ++ } ++ + By(""test that we DO get a routing loop"") + // (In order to test that the tryRoutingLoop setup is genuine.) + tryRoutingLoop(true)",qq: Should this include the iptables6-save sim. to the inverse checks above? +741,"@@ -195,8 +195,16 @@ func (cfg *Config) Merge(rhs Config) *Config { + + for i := 0; i < left.NumField(); i++ { + leftField := left.Field(i) +- if utils.ZeroOrNil(leftField.Interface()) { +- leftField.Set(reflect.ValueOf(right.Field(i).Interface())) ++ switch leftField.Interface().(type) { ++ case BooleanDefaultFalse, BooleanDefaultTrue: ++ str, _ := json.Marshal(reflect.ValueOf(leftField.Interface()).Interface()) ++ if string(str) == ""null"" { ++ leftField.Set(reflect.ValueOf(right.Field(i).Interface())) ++ } ++ default: ++ if utils.ZeroOrNil(leftField.Interface()) { ++ leftField.Set(reflect.ValueOf(right.Field(i).Interface())) ++ } + } + } + ",im open to explicitly checking NotSet value here but json logic already handles it so kept it this way. +742,"@@ -27,6 +27,7 @@ extern ""C"" { + #include ""ScriptingEnvironment.h"" + #include ""../typedefs.h"" + #include ""../Util/OpenMPWrapper.h"" ++#include ""../Util/Lua.h"" + + ScriptingEnvironment::ScriptingEnvironment() {} + ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {",The naming of the include file appears to be unlucky. +743,"@@ -1018,7 +1018,8 @@ class BarPlot(BarsMixin, ColorbarPlot, LegendPlot): + if self.show_legend and any(len(l) for l in labels) and (sdim or not self.multi_level): + leg_spec = self.legend_specs[self.legend_position] + if self.legend_cols: leg_spec['ncol'] = self.legend_cols +- axis.legend(title=title, **leg_spec) ++ self.legend_opts.update(**leg_spec) ++ axis.legend(title=title, **self.legend_opts) + + return bars, xticks, ax_dims + ",Bit worried about this. At minimum you should make a copy of the dict here to avoid modifying a user supplied variable. +744,"@@ -455,6 +455,11 @@ func (r *AWSMachinePoolReconciler) reconcileLaunchTemplate(machinePoolScope *sco + // userdata, OR we've discovered a new AMI ID. + if needsUpdate || tagsChanged || *imageID != *launchTemplate.AMI.ID || launchTemplateUserDataHash != bootstrapDataHash { + machinePoolScope.Info(""creating new version for launch template"", ""existing"", launchTemplate, ""incoming"", machinePoolScope.AWSMachinePool.Spec.AWSLaunchTemplate) ++ // There is a limit to the number of Launch Template Versions. ++ // We ensure that the number of versions does not grow without bound by following a simple rule: For each version we create, we delete one old version. ++ if err := ec2svc.PruneLaunchTemplateVersions(machinePoolScope.AWSMachinePool.Status.LaunchTemplateID); err != nil { ++ return err ++ } + if err := ec2svc.CreateLaunchTemplateVersion(machinePoolScope, imageID, bootstrapData); err != nil { + return err + }","Is it better to create one before pruning? In case creation fails we don't want to delete the previous one. We create a new one, it is tagged as latest, so the previous can be deleted. `CreateLaunchTemplateVersion` returns the version created, how about directly trying to delete the previous version? Assuming the numbering is strictly increasing." +745,"@@ -27,13 +27,13 @@ class ContainerInformationTab extends Tab { + + private final WinePrefixContainerDTO container; + +- private Consumer onDeletePrefix; ++ private Consumer onDeleteContainer; + private Consumer onOpenFileBrowser; + +- ContainerInformationTab(WinePrefixContainerDTO container) { ++ ContainerInformationTab(ContainerDTO container) { + super(tr(""Information"")); + +- this.container = container; ++ this.container = (WinePrefixContainerDTO) container; // TODO: use generic container + + this.setClosable(false); + ",Do we require the specific implementation information here? +746,"@@ -0,0 +1,13 @@ ++class DomainBlacklist < ActiveRecord::Base ++ validates :domain, uniqueness: { case_sensitive: false } ++ ++ class << self ++ def email_banned?(email_address) ++ contains?(email_address.split('@').last) ++ end ++ ++ def contains?(domain) ++ exists?(['lower(domain) LIKE ?', ""%#{domain.downcase}%""]) ++ end ++ end ++end","How about `exists?(['domain ~* ?', domain.downcase])` ?" +747,"@@ -729,6 +729,15 @@ func newContextForLongPoll(c *cli.Context) (context.Context, context.CancelFunc) + return newContextWithTimeout(c, defaultContextTimeoutForLongPoll) + } + ++func newContextForBackground(c *cli.Context) (context.Context, context.CancelFunc) { ++ if c.GlobalIsSet(FlagContextTimeout) { ++ timeout := time.Duration(c.GlobalInt(FlagContextTimeout)) * time.Second ++ return rpc.NewContextWithTimeoutAndCLIHeaders(timeout) ++ } ++ ++ return rpc.NewContextWithCLIHeaders() ++} ++ + func newContextWithTimeout(c *cli.Context, timeout time.Duration) (context.Context, context.CancelFunc) { + if c.GlobalIsSet(FlagContextTimeout) { + timeout = time.Duration(c.GlobalInt(FlagContextTimeout)) * time.Second",Is this getting used in other places? Can we switch all the places to use the new API you added? +748,"@@ -483,17 +483,6 @@ int HTTP_OP::libcurl_exec( + curl_easy_setopt(curlEasy, CURLOPT_SSL_VERIFYPEER, 1L); + //curl_easy_setopt(curlEasy, CURLOPT_SSL_VERIFYPEER, FALSE); + +- // if the above is nonzero, you need the following: +- // +-#ifndef _WIN32 +- if (boinc_file_exists(CA_BUNDLE_FILENAME)) { +- // call this only if a local copy of ca-bundle.crt exists; +- // otherwise, let's hope that it exists in the default place +- // +- curl_easy_setopt(curlEasy, CURLOPT_CAINFO, CA_BUNDLE_FILENAME); +- } +-#endif +- + // set the user agent as this boinc client & version + // + curl_easy_setopt(curlEasy, CURLOPT_USERAGENT, g_user_agent_string);","This need to be checked with linux. AFAIK, we have this file in our bin directory that is a link to the system file." +749,"@@ -1,12 +1,12 @@ +-define(['browser', 'dom', 'layoutManager', 'css!components/viewManager/viewContainer'], function (browser, dom, layoutManager) { +- 'use strict'; ++import 'css!components/viewManager/viewContainer'; ++/* eslint-disable indent */ + + function setControllerClass(view, options) { + if (options.controllerFactory) { + return Promise.resolve(); + } + +- var controllerUrl = view.getAttribute('data-controller'); ++ let controllerUrl = view.getAttribute('data-controller'); + + if (controllerUrl) { + if (controllerUrl.indexOf('__plugin/') === 0) {",Shouldn't we import `default`? I can't get here to test. +750,"@@ -99,7 +99,7 @@ class UNIXServerClient(object): + self.unix_socket = os.path.join(self.temp_dir, 'luigid.sock') + + def run_server(self): +- luigi.server.run(unix_socket=unix_socket) ++ luigi.server.run(unix_socket=self.unix_socket) + + def scheduler(self): + url = ParseResult(","!!!!!!!!!!!!! @graingert, does this mean that tests haven't been running???" +751,"@@ -484,11 +484,11 @@ namespace Microsoft.DotNet.Execute + public string FormatSetting(string option, string value, string type, string toolName) + { + string commandOption = null; +- if (type.Equals(""passThrough"")) ++ if (type != null && type.Equals(""passThrough"")) + { + commandOption = string.Format("" {0}"", toolName.Equals(""console"") ? """" : value); + } +- else if (type.Equals(RunToolSettingValueTypeReservedKeyword)) { /* do nothing */ } ++ else if (type != null && type.Equals(RunToolSettingValueTypeReservedKeyword)) { /* do nothing */ } + else + { + Tool toolFormat;","I've already tried the null-coalescing operator here and got a strange error, so did this the old-fashioned way." +752,"@@ -1,4 +1,11 @@ + var parent = axe.commons.dom.getComposedParent(node); +-return (['UL', 'OL'].includes(parent.nodeName.toUpperCase()) || +- (parent.getAttribute('role') || '').toLowerCase() === 'list'); +- ++ ++var parentRole = (parent.getAttribute('role') || '').toLowerCase(); ++ ++var isListRole = parentRole === 'list'; ++ ++return ( ++ (['UL', 'OL'].includes(parent.nodeName.toUpperCase()) && ++ (!parentRole || isListRole)) || ++ isListRole ++);",This doesn't follow our spacing convention. It's also a little hard to read. Can you reformat? +753,"@@ -4,10 +4,10 @@ + package stack + + import ( +- ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/template"" + ""github.com/aws/aws-sdk-go/service/cloudformation"" ++ ""github.com/aws/copilot-cli/internal/pkg/template"" + +- ""github.com/aws/amazon-ecs-cli-v2/internal/pkg/deploy"" ++ ""github.com/aws/copilot-cli/internal/pkg/deploy"" + ) + + const pipelineCfnTemplatePath = ""cicd/pipeline_cfn.yml""","The deploy should come before template? EDIT: I see that in other files, we put a separate line and put deploy at the end. What is the reason for this?" +754,"@@ -60,7 +60,7 @@ public class Program + // turn off the above default. i.e any + // instrument which does not match any views + // gets dropped. +- // .AddView(instrumentName: ""*"", new DropAggregationConfig()) ++ // .AddView(instrumentName: ""*"", new MetricStreamConfiguration() { Aggregation = Aggregation.Drop }) + .AddConsoleExporter() + .Build(); + ",Consider making a constant (e.g. `MetricStreamConfiguration.Drop`). +755,"@@ -18,6 +18,7 @@ try: + except ImportError: + from rdkit.piddle import piddle + import ClusterUtils ++from rdkit.six.moves import xrange + + import numpy + ",same question: why not just switch this to range too? +756,"@@ -111,10 +111,10 @@ Variable IO::InquireVariable(const std::string &name) + helper::CheckForNullptr(m_IO, ""for variable "" + name + + "", in call to IO::InquireVariable""); + +- const std::string type(m_IO->InquireVariableType(name)); ++ const Type type(m_IO->InquireVariableType(name)); + core::VariableBase *variable = nullptr; + +- if (type == ""unknown"") ++ if (type == Type::None) + { + } + #define declare_template_instantiation(T) \","@chuckatkins most places used an empty string for ""no type"", but a few used `""unknown""`. I've converted both cases to `Type::None`. Do you know why there was a distinction before?" +757,"@@ -408,7 +408,7 @@ void CUDATreeLearner::copyDenseFeature() { + // looking for dword_features_ non-sparse feature-groups + if (!train_data_->IsMultiGroup(i)) { + dense_feature_group_map_.push_back(i); +- auto sizes_in_byte = train_data_->FeatureGroupSizesInByte(i); ++ auto sizes_in_byte = std::min(train_data_->FeatureGroupSizesInByte(i), static_cast(num_data_)); + void* tmp_data = train_data_->FeatureGroupData(i); + Log::Debug(""Started copying dense features from CPU to GPU - 2""); + CUDASUCCESS_OR_FATAL(cudaMemcpyAsync(&device_features[copied_feature * num_data_], tmp_data, sizes_in_byte, cudaMemcpyHostToDevice, stream_[device_id]));",should we assert for the type for `FeatureGroupData` ? I think it should be 1-Byte type. +758,"@@ -51,10 +51,10 @@ class TestCube(ComparisonTestCase): + def test_dimension_values_vdim(self): + cube = Dataset(self.cube, kdims=['longitude', 'latitude']) + self.assertEqual(cube.dimension_values('unknown', flat=False), +- np.flipud(np.array([[ 0, 4, 8], +- [ 1, 5, 9], +- [ 2, 6, 10], +- [ 3, 7, 11]], dtype=np.int32).T)) ++ np.array([[ 0, 4, 8], ++ [ 1, 5, 9], ++ [ 2, 6, 10], ++ [ 3, 7, 11]], dtype=np.int32).T) + + def test_range_kdim(self): + cube = Dataset(self.cube, kdims=['longitude', 'latitude'])",As long as you are sure this is definitely correct now... :-) +759,"@@ -166,7 +166,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL + tempBasal.setVisibility(View.GONE); + tempBasalCancel.setVisibility(View.VISIBLE); + final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); +- tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + ""\n"" + activeTemp.toStringShort()); ++ tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + "" "" + activeTemp.toStringShort()); + } else { + tempBasal.setVisibility(View.VISIBLE); + tempBasalCancel.setVisibility(View.GONE);",... so that all action buttons have the same height :-) +760,"@@ -21,6 +21,12 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include + + #include + #include ","Use correct, alpha sorted, include order. Correct order means: 1. Header corresponding to this source (i.e. `""LatencyTestPublisher.hpp""`) 2. C system headers 3. C++ system headers 4. Alpha-sorted external libraries headers 5. Alpha-sorted public headers from this project 6. Alpha-sorted private headers" +761,"@@ -58,6 +58,10 @@ type OutboundOption func(*Outbound) + + func (OutboundOption) httpOption() {} + ++// RequestFactory allows clients to configure their outgoing http requests. If not set, ++// a default implemenation will use the HostPort to make a POST request with the request body. ++type RequestFactory func(*transport.Request) (*http.Request, error) ++ + // URLTemplate specifies the URL this outbound makes requests to. For + // peer.Chooser-based outbounds, the peer (host:port) spection of the URL may + // vary from call to call but the rest will remain unchanged. For single-peer","I hate this name, open to suggestions." +762,"@@ -199,7 +199,13 @@ func (c *Client) locallyCacheResults(target *core.BuildTarget, digest *pb.Digest + } + data, _ := proto.Marshal(ar) + metadata.RemoteAction = data +- c.state.Cache.Store(target, c.localCacheKey(digest), nil) ++ // TODO(jpoole): Similar to retrieveTargetMetadataFromCache, it would be cleaner if we could store ++ // into the cache from an arbitrary reader. ++ if err := build.StoreTargetMetadata(target, metadata); err != nil { ++ log.Warning(""%s"", err) ++ return ++ } ++ c.state.Cache.Store(target, c.localCacheKey(digest), []string{target.TargetBuildMetadataFileName()}) + } + + // retrieveLocalResults retrieves locally cached results for a target if possible.",Does this log line work? We need Warningf or just warning without the format string. +763,"@@ -62,6 +62,7 @@ func New(checkpointer export.Checkpointer, exporter export.Exporter, opts ...Opt + impl := sdk.NewAccumulator( + checkpointer, + sdk.WithResource(c.Resource), ++ sdk.WithMetricsProcessors(c.MetricsProcessors...), + ) + return &Controller{ + provider: registry.NewMeterProvider(impl),",The pull controller would need similar updates. +764,"@@ -1,5 +1,5 @@ + /** +- * Copyright 2015-2017 The OpenZipkin Authors ++ * Copyright 2015-2018 The OpenZipkin Authors + * + * 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",ignore this.. just didn't want to litter with a commit update to satisfy license plugin +765,"@@ -807,8 +807,8 @@ module Beaker + end + + if host['is_cygwin'].nil? or host['is_cygwin'] == true +- dest = ""/cygdrive/c/Windows/Temp/#{host['dist']}.msi"" +- on host, ""curl -O #{dest} #{link}"" ++ dest = ""#{host['dist']}.msi"" ++ on host, ""curl -O #{link}"" + + #Because the msi installer doesn't add Puppet to the environment path + #Add both potential paths for simplicity",Is this definition needed since it doesn't look like it's being used anywhere? +766,"@@ -35,6 +35,11 @@ module Mongoid + class << self + delegate :discriminator_key, to: ::Mongoid + end ++ end ++ ++ unless fields.has_key?(self.discriminator_key) || descendants.length == 0 ++ default_proc = lambda { self.class.name } ++ field(self.discriminator_key, default: default_proc, type: String) + end + end + end",Can this condition be reworded using `if` please? +767,"@@ -135,13 +135,15 @@ Status FetchEdgesExecutor::setupEdgeKeysFromRef() { + const InterimResult *inputs; + if (sentence_->ref()->isInputExpr()) { + inputs = inputs_.get(); +- if (inputs == nullptr) { ++ if (inputs == nullptr ++ || (inputs != nullptr && !inputs->hasData())) { + // we have empty imputs from pipe. + return Status::OK(); + } + } else { + inputs = ectx()->variableHolder()->get(varname_); +- if (inputs == nullptr) { ++ if (inputs == nullptr ++ || (inputs != nullptr && !inputs->hasData())) { + return Status::Error(""Variable `%s' not defined"", varname_.c_str()); + } + }","after ||, no need inputs != nullptr" +768,"@@ -159,7 +159,14 @@ func (s *Source) Owner() (string, error) { + // is deloying to and the containerized applications that will be deployed. + type PipelineStage struct { + *AssociatedEnvironment +- LocalApplications []string ++ LocalApplications []AppInStage ++} ++ ++// AppInStage represents configurations for an app in a pipeline stage ++type AppInStage struct { ++ Name string ++ // the path to the integration test buildspec for this action ++ IntegTestBuildspecPath string + } + + // AppTemplatePath returns the full path to the application CFN template",Is it just preference or on purpose that using slice of structs instead of slice of pointers? +769,"@@ -90,7 +90,7 @@ export function diff(parentDom, newVNode, oldVNode, context, isSvg, excessDomChi + c.state = c._nextState; + c._dirty = false; + c._vnode = newVNode; +- newVNode._dom = oldDom!=null ? oldDom!==oldVNode._dom ? oldDom : oldVNode._dom : null; ++ newVNode._dom = oldVNode._dom; + newVNode._children = oldVNode._children; + for (tmp = 0; tmp < newVNode._children.length; tmp++) { + if (newVNode._children[tmp]) newVNode._children[tmp]._parent = newVNode;",This line always confused me anyway. Good catch! +770,"@@ -130,6 +130,6 @@ func (j journalBlockServer) IsUnflushed(ctx context.Context, tlfID tlf.ID, + } + + func (j journalBlockServer) Shutdown() { +- j.jServer.shutdown() ++ j.jServer.shutdown(context.Background()) + j.BlockServer.Shutdown() + }","Should we add `ctx` to `BlockServer.Shutdown()` for this purpose? Would be nice, but I don't care too much." +771,"@@ -42,7 +42,7 @@ bool DeadlineQosPolicy::addToCDRMessage(CDRMessage_t* msg) + bool valid = CDRMessage::addUInt16(msg, this->Pid); + valid &= CDRMessage::addUInt16(msg, this->length);//this->length); + valid &= CDRMessage::addInt32(msg,period.seconds); +- valid &= CDRMessage::addUInt32(msg,period.fraction); ++ valid &= CDRMessage::addUInt32(msg,period.nanosec); + return valid; + } + ",Duration_t at RTPS level must be serialized using fractions. +772,"@@ -28,6 +28,14 @@ import ( + ""go.uber.org/yarpc/yarpcerrors"" + ) + ++var msgInboundDispatcherNotRunning = ""peer for service %q is not running"" ++ ++// NotRunningInboundError builds a YARPC error with code ++// yarpcerrors.CodeUnavailable when the dispatcher is not running. ++func NotRunningInboundError(service string) error { ++ return yarpcerrors.UnavailableErrorf(msgInboundDispatcherNotRunning, service) ++} ++ + // RequestBodyDecodeError builds a YARPC error with code + // yarpcerrors.CodeInvalidArgument that represents a failure to decode + // the request body.","""peer"" has its own meaning within YARPC with its own class of objects. This should probably be ""dispatcher"" too?" +773,"@@ -172,9 +172,18 @@ class ClangSA(analyzer_base.SourceAnalyzer): + '-Xclang', checker_name]) + + if config.ctu_dir and not self.__disable_ctu: ++ # ctu-clang5 compatibility + analyzer_cmd.extend(['-Xclang', '-analyzer-config', + '-Xclang', +- 'xtu-dir=' + self.get_xtu_dir()]) ++ 'xtu-dir=' + self.get_ctu_dir()]) ++ # ctu-clang6 compatibility (5.0 and 6.0 options work together) ++ analyzer_cmd.extend(['-Xclang', '-analyzer-config', ++ '-Xclang', ++ 'experimental-enable-naive-ctu-analysis' ++ '=true', ++ '-Xclang', '-analyzer-config', ++ '-Xclang', ++ 'ctu-dir=' + self.get_ctu_dir()]) + if config.ctu_has_analyzer_display_ctu_progress: + analyzer_cmd.extend(['-Xclang', + '-analyzer-display-ctu-progress'])",I do not like this line break before `=true`. Maybe starting the list in the next line would help to reduce the indent? This way we could keep this string together. +774,"@@ -34,18 +34,10 @@ import ( + // the default value in Default var. + + func init() { +- flag.StringVar(&_overwritePath, ""config-path"", """", ""Config path"") +- flag.StringVar(&_secretPath, ""secret-path"", """", ""Secret path"") +- flag.StringVar(&_subChainPath, ""sub-config-path"", """", ""Sub chain Config path"") + flag.Var(&_plugins, ""plugin"", ""Plugin of the node"") + } + + var ( +- // overwritePath is the path to the config file which overwrite default values +- _overwritePath string +- // secretPath is the path to the config file store secret values +- _secretPath string +- _subChainPath string + _plugins strs + _evmNetworkID uint32 + loadChainID sync.Once",_plugins should be removed too +775,"@@ -0,0 +1,5 @@ ++let nn = node.nodeName.toLowerCase(); ++let validSetup = ++ node.hasAttribute('alt') && (nn === 'img' || nn === 'input' || nn === 'area'); ++let validAttrValue = /^\s+$/.test(node.getAttribute('alt')); ++return validSetup && validAttrValue;","The rule selector will not include `` and `` elements. Why not make this a new, separate rule altogether?" +776,"@@ -1122,7 +1122,7 @@ class CommandDispatcher: + try: + userscripts.run_async(tab, cmd, *args, win_id=self._win_id, + env=env, verbose=verbose) +- except userscripts.UnsupportedError as e: ++ except (userscripts.UnsupportedError, userscripts.NotFoundError) as e: + raise cmdexc.CommandError(e) + + @cmdutils.register(instance='command-dispatcher', scope='window')",@The-Compiler Is this style okay or would you prefer a common userscript exception base? +777,"@@ -98,7 +98,8 @@ SchemaBuffer.prototype.cast = function (value, doc, init) { + + return value; + } else if (value instanceof Binary) { +- return new MongooseBuffer(value.value(true), [this.path, doc]); ++ var sub_type = value.sub_type || 0x00; ++ return (new MongooseBuffer(value.value(true), [this.path, doc])).toObject(sub_type); + } + + if (null === value) return value;",we'd need to return a MongooseBuffer here instead of the Binary. lets add the subtype option to the buffer schema type as referenced in #1000 instead. +778,"@@ -1158,7 +1158,6 @@ function updateDocuments(coll, selector, document, options, callback) { + if ('function' === typeof options) (callback = options), (options = null); + if (options == null) options = {}; + if (!('function' === typeof callback)) callback = null; +- + // If we are not providing a selector or document throw + if (selector == null || typeof selector !== 'object') + return callback(toError('selector must be a valid JavaScript object'));",Let's remove this change. +779,"@@ -727,7 +727,7 @@ def processNegativeStates(role, states, reason, negativeStates=None): + # but only if it is either focused or this is something other than a change event. + # The condition stops ""not selected"" from being spoken in some broken controls + # when the state change for the previous focus is issued before the focus change. +- if role in (ROLE_LISTITEM, ROLE_TREEVIEWITEM, ROLE_TABLEROW) and STATE_SELECTABLE in states and (reason != REASON_CHANGE or STATE_FOCUSED in states): ++ if role in (ROLE_LISTITEM, ROLE_TREEVIEWITEM, ROLE_TABLEROW,ROLE_TABLECELL,ROLE_TABLECOLUMNHEADER,ROLE_TABLEROWHEADER) and STATE_SELECTABLE in states and (reason != REASON_CHANGE or STATE_FOCUSED in states): + speakNegatives.add(STATE_SELECTED) + # Restrict ""not checked"" in a similar way to ""not selected"". + if (role in (ROLE_CHECKBOX, ROLE_RADIOBUTTON, ROLE_CHECKMENUITEM) or STATE_CHECKABLE in states) and (STATE_HALFCHECKED not in states) and (reason != REASON_CHANGE or STATE_FOCUSED in states):",Could you split this into multiple lines? +780,"@@ -25,12 +25,17 @@ import { __ } from '@wordpress/i18n'; + /** + * Internal dependencies + */ +-import Layout from '../../../components/layout/layout'; ++import Data from 'googlesitekit-data'; + import DashboardModuleHeader from '../../../components/dashboard/dashboard-module-header'; + import DashboardPageSpeed from '../components/DashboardPageSpeed'; ++import { STORE_NAME } from '../../../googlesitekit/datastore/site/constants'; ++const { useSelect } = Data; + + function DashboardSpeed() { +- const description = global.googlesitekit.permaLink ? __( 'How fast this page is.', 'google-site-kit' ) : __( 'How fast your home page is.', 'google-site-kit' ); ++ const currentEntityURL = useSelect( ( select ) => select( STORE_NAME ).getCurrentEntityURL() ); ++ const description = currentEntityURL ++ ? __( 'How fast your page loads, how quickly people can interact with your content, and how stable your content is.', 'google-site-kit' ) ++ : __( 'How fast your home page loads, how quickly people can interact with your content, and how stable your content is.', 'google-site-kit' ); + + return ( + ","This technically works, however it may be safer to use both `getCurrentReferenceURL` and `getCurrentEntityURL` and then make this condition `currentReferenceURL === currentEntityURL`. Currently, this code only works based on the internals of `getCurrentReferenceURL`, so by checking both we would decouple that." +781,"@@ -69,9 +69,9 @@ func (c *WSClient) Connect() (conn.Connection, error) { + if resp != nil { + body, errRead := ioutil.ReadAll(resp.Body) + if errRead == nil { +- respMsg = fmt.Sprintf(""response code: %d, response body: %s"", resp.StatusCode, string(body)) ++ respMsg = fmt.Sprintf(""Response code: %d, response body: %s"", resp.StatusCode, string(body)) + } else { +- respMsg = fmt.Sprintf(""response code: %d"", resp.StatusCode) ++ respMsg = fmt.Sprintf(""Response code: %d"", resp.StatusCode) + } + resp.Body.Close() + }",It does not recommend capitalization +782,"@@ -113,6 +113,17 @@ feature 'User creates a subscription' do + expect(page).to have_content(I18n.t('subscriptions.flashes.update.success')) + end + ++ scenario 'updates Stripe subscription with declining credit card', :js => true do ++ FakeStripe.failure = true ++ sign_in_as_subscriber ++ visit my_account_path ++ submit_declining_credit_card_info ++ ++ expect(current_path).to eq my_account_path ++ expect(page).to_not have_content(I18n.t('subscriptions.flashes.update.success')) ++ expect(page).to have_content 'Your credit card was declined' ++ end ++ + scenario 'does not see option to update billing if not subscribing' do + visit my_account_path + ","Minor thing, but can you use 1.9 hash syntax for this?" +783,"@@ -361,6 +361,7 @@ class LambdaExecutorReuseContainers(LambdaExecutorContainers): + + mount_volume = not config.LAMBDA_REMOTE_DOCKER + lambda_cwd_on_host = Util.get_host_path_for_path_in_docker(lambda_cwd) ++ lambda_cwd_on_host = Util.format_windows_path(lambda_cwd) + mount_volume_str = '-v ""%s"":/var/task' % lambda_cwd_on_host if mount_volume else '' + + # Create and start the container",I tried to follow the code structure already present. +784,"@@ -191,7 +191,7 @@ public class FileHandler { + final long copied = Files.copy(from.toPath(), out); + final long length = from.length(); + if (copied != length) { +- throw new IOException(""Could not transfer all bytes.""); ++ throw new IOException(""Could not transfer all bytes of "" + from.toPath()); + } + } + }",seems reasonable to also want to include the 'to' location? +785,"@@ -118,7 +118,7 @@ class ExperimentTestBaseClass(HelperTestCaseBase): + global g_myEnv + if not g_myEnv: + # Setup environment +- params = type('obj', (object,), {'installDir' : os.environ['NUPIC']}) ++ params = type('obj', (object,), {'installDir' : resource_filename(""nupic"","""")}) + g_myEnv = MyTestEnvironment(params) + + ",Please leave 1 space char between commas here and other places in this PR. +786,"@@ -100,8 +100,8 @@ bool ThreadsExec::spawn() { + + pthread_attr_t attr; + +- if (0 == pthread_attr_init(&attr) || +- 0 == pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) || ++ if (0 == pthread_attr_init(&attr) && ++ 0 == pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) && + 0 == pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) { + pthread_t pt; + ",hm is this really &&? Not ||? Was it initially correct if any of these things are not set that it needs to recreated? +787,"@@ -149,7 +149,8 @@ public class PackageTool extends SolrCLI.ToolBase { + String version = parsedVersion.second(); + boolean noprompt = cli.hasOption('y'); + boolean isUpdate = cli.hasOption(""update"") || cli.hasOption('u'); +- packageManager.deploy(packageName, version, PackageUtils.validateCollections(cli.getOptionValue(""collections"").split("","")), cli.getOptionValues(""param""), isUpdate, noprompt); ++ String collections[] = cli.hasOption(""collections"")? PackageUtils.validateCollections(cli.getOptionValue(""collections"").split("","")): new String[] {}; ++ packageManager.deploy(packageName, version, collections, cli.hasOption(""cluster""), cli.getOptionValues(""param""), isUpdate, noprompt); + break; + } + case ""undeploy"":",Please don't use C-style array declarations. IMO our pre-commit ought to be enhanced to not allow this +788,"@@ -259,6 +259,12 @@ bool pmix_value_cmp(pmix_value_t *p, pmix_value_t *p1) + case PMIX_STRING: + rc = strcmp(p->data.string, p1->data.string); + break; ++ case PMIX_COMPRESSED_STRING: ++ if (p->data.bo.size != p1->data.bo.size) { ++ return false; ++ } else { ++ return true; ++ } + case PMIX_STATUS: + rc = (p->data.status == p1->data.status); + break;",@rhc54 This doesn't look like a comprehensive comparison. For `PMIX_STRING` we seem to actually compare the content of the data while here we only compare meta-information which doesn't ensure that values are the same. +789,"@@ -1601,6 +1601,7 @@ void nano::json_handler::bootstrap () + { + std::string address_text = request.get (""address""); + std::string port_text = request.get (""port""); ++ const bool confirmed_frontiers = request.get (""confirmed_frontiers"", false); + boost::system::error_code address_ec; + auto address (boost::asio::ip::address_v6::from_string (address_text, address_ec)); + if (!address_ec)",I think `bypass_frontier_confirmation` conveys the intention better (default false as well) +790,"@@ -5,12 +5,9 @@ import ( + ""fmt"" + ""testing"" + +- ""github.com/ipfs/go-cid"" +- ""github.com/ipfs/go-hamt-ipld"" +- ""github.com/pkg/errors"" + ""github.com/stretchr/testify/assert"" +- ""github.com/stretchr/testify/require"" + ++ ""github.com/filecoin-project/go-filecoin/address"" + ""github.com/filecoin-project/go-filecoin/chain"" + ""github.com/filecoin-project/go-filecoin/config"" + ""github.com/filecoin-project/go-filecoin/core""","This looks like it goes beyond the scope of removing `BlockHeight()`, in the future please do this in a separate commit at a minimum -- separate PR is fine too." +791,"@@ -666,9 +666,10 @@ class AbstractAudio(QObject): + muted_changed = pyqtSignal(bool) + recently_audible_changed = pyqtSignal(bool) + +- def __init__(self, parent=None): ++ def __init__(self, tab, parent=None): + super().__init__(parent) + self._widget = None ++ self._tab = tab + + def set_muted(self, muted: bool): + """"""Set this tab as muted or not.""""""",You'll also need to adjust `FakeWebTabAudio` in `tests/helpers/stubs.py`. +792,"@@ -1,19 +1,3 @@ +-/* +-Copyright 2019 The Kubernetes Authors. +- +-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 helpers + + import (",@csrwng what should we do here? This one is from origin. +793,"@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include + #include ",Follow alphabetical order. +794,"@@ -0,0 +1,16 @@ ++// ++// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. ++// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. ++// ++ ++namespace Datadog.Trace.ClrProfiler ++{ ++ internal interface IAutomaticTracer : ICommonTracer ++ { ++ object GetDistributedTrace(); ++ ++ void SetDistributedTrace(object trace); ++ ++ void Register(object manualTracer); ++ } ++}","As far as I can tell, these always get and set the context as an `IReadOnlyDictionary`. Can we use that here instead of `object` and get rid of the `as IReadOnlyDictionary`?" +795,"@@ -206,7 +206,7 @@ class CompletionItemDelegate(QStyledItemDelegate): + else: + self._doc.setPlainText(self._opt.text) + else: +- self._doc.setHtml('{}'.format(html.escape(self._opt.text))) ++ self._doc.setHtml('{}'.format(html.escape(self._opt.text))) + + def _draw_focus_rect(self): + """"""Draw the focus rectangle of an ItemViewItem.""""""","As you only have `{}` as the format string (without anything else in it), this is the same as doing `self._doc.setHtml(html.escape(self._opt.text))`" +796,"@@ -161,6 +161,8 @@ public class Constants { + + // enable Quartz Scheduler if true. + public static final String ENABLE_QUARTZ= ""azkaban.server.schedule.enable_quartz""; ++ ++ public static final String CUSTOM_CREDENTIAL_NAME = ""azkaban.security.credential""; + } + + public static class FlowProperties {",Where would this be configured? In azkaban.properties? +797,"@@ -2101,6 +2101,12 @@ Collection.prototype.findOneAndUpdate = function(filter, update, options, callba + if (typeof options === 'function') (callback = options), (options = {}); + options = options || {}; + ++ var err = checkForAtomicOperators(update); ++ if (err) { ++ if (typeof callback === 'function') return callback(err); ++ return this.s.promiseLibrary.reject(err); ++ } ++ + // Basic validation + if (filter == null || typeof filter !== 'object') + throw toError('filter parameter must be an object');",1. Use `const` instead of `var` here. 2. Move the check to after the `if (update == null || typeof update !== 'object')`. +798,"@@ -29,6 +29,13 @@ struct st_h2o_multithread_queue_t { + #if H2O_USE_LIBUV + uv_async_t async; + #else ++#if defined(__linux__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) ++/** ++ * The kernel overhead of an eventfd file descriptor is ++ * much lower than that of a pipe, and only one file descriptor is required ++ */ ++#define H2O_ASYNC_NOTIFY_USING_EVENTFD ++#endif + struct { + int write; + h2o_socket_t *read;","Let's assume that on Linux `eventfd` is always available as a wrapper of the eventfd2 system call. It is supported since linux 2.6.27 + glibc 2.9, as well as from the ancient versions of bionic. In other words, it would be fair to argue that the pair would be available on practically all platforms that provide `pipe2`. Therefore switching from using `pipe2` to `eventfd` on linux unconditionally would not cause issues on our users." +799,"@@ -61,6 +61,7 @@ public class DatabaseTransferConsumer implements IDataTransferConsumer e ++ @logger.warn ""Attemped ssh.close. Caught an error: #{e.message} Attempting ssh.shutdown!..."" ++ begin ++ @ssh.shutdown! ++ rescue => e ++ @logger.warn ""Attemped ssh.shutdown!. Caught an error: #{e.message}. Giving up and destorying ssh."" ++ @ssh = nil ++ end + end + @ssh = nil + end",would be good to have a test for the case when `shutdown!` raises +801,"@@ -2747,6 +2747,10 @@ short HbaseInsert::codeGen(Generator *generator) + + generator->initTdbFields(hbasescan_tdb); + ++ if (CmpCommon::getDefault(HBASE_ASYNC_OPERATIONS) == DF_ON ++ && t == ComTdbHbaseAccess::INSERT_) ++ hbasescan_tdb->setAsyncOperations(TRUE); ++ + if (getTableDesc()->getNATable()->isSeabaseTable()) + { + hbasescan_tdb->setSQHbaseTable(TRUE);",Does upsert pass this check also? +802,"@@ -43,6 +43,9 @@ func (r *helper) Patch(name types.NamespacedName, kind, apiVersion string, patch + WithField(""stderr"", ioStreams.ErrOut.(*bytes.Buffer).String()).Warn(""running the patch command failed"") + return err + } ++ r.logger. ++ WithField(""stdout"", ioStreams.Out.(*bytes.Buffer).String()). ++ WithField(""stderr"", ioStreams.ErrOut.(*bytes.Buffer).String()).Info(""patch command successful"") + return nil + } + ","Apologies reviewers, I did end up pushing another change. I was starting to request SRE-P help to get the apiserver configs from some clusters before and after when I realized I can just log the stdout from the patch command to see if anything was changed or not. Much simpler to verify if my work did or did not make changes to the config during the transition. Also got the spacing issue you mentioned @abhinavdahiya Thanks all." +803,"@@ -23,6 +23,7 @@ import ( + const ( + kbfsRepoDir = "".kbfs_git"" + kbfsConfigName = ""kbfs_config"" ++ kbfsConfigNameTemp = ""._kbfs_config"" + gitSuffixToIgnore = "".git"" + kbfsDeletedReposDir = "".kbfs_deleted_repos"" + )",I'm not sure this naming is a good idea; that's the format for macOS xattr metadata files on unsupported filesystems. +804,"@@ -1,4 +1,4 @@ +-class AddIndexOnSectionIdAndTeacherIdToSectionTeachers < ActiveRecord::Migration ++class AddIndexOnSectionIdAndTeacherIdToSectionTeachers < ActiveRecord::Migration[4.2] + def up + change_table :section_teachers do |t| + t.remove_index :section_id",Metrics/LineLength: Line is too long. [85/80] +805,"@@ -19,12 +19,13 @@ + + package org.apache.iceberg.flink; + +- + import java.util.List; + import org.apache.flink.table.api.SqlParserException; + import org.apache.iceberg.AssertHelpers; + import org.apache.iceberg.FileFormat; + import org.apache.iceberg.catalog.Namespace; ++import org.apache.iceberg.events.Listeners; ++import org.apache.iceberg.events.ScanEvent; + import org.apache.iceberg.relocated.com.google.common.collect.Lists; + import org.junit.After; + import org.junit.Assert;",Please remove these imports. The project's style is to use `Assert.assertEquals` and not import static methods in general. This also caused a lot of unnecessary changes. +806,"@@ -112,7 +112,10 @@ static int http_post(struct flb_out_http *ctx, + payload_buf, payload_size, + ctx->host, ctx->port, + ctx->proxy, 0); +- ++ if (!c) { ++ flb_plg_error(ctx->ins, ""[http_client] failed to create HTTP client""); ++ return FLB_RETRY; ++ } + + if (c->proxy.host) { + flb_plg_debug(ctx->ins, ""[http_client] proxy host: %s port: %i"",","thanks. Note that returning at this point might leak memory from the allocations above, so the PR will need to take care of that too." +807,"@@ -492,10 +492,13 @@ class MainWindow(QWidget): + @pyqtSlot(bool) + def _on_fullscreen_requested(self, on): + if on: +- self.state_before_fullscreen = self.windowState() +- self.showFullScreen() ++ self.window_state_before_fullscreen = self.windowState() ++ self.config_state_before_fullscreen = config.val.content.desktop_fullscreen ++ if config.val.content.desktop_fullscreen: ++ self.showFullScreen() + elif self.isFullScreen(): +- self.setWindowState(self.state_before_fullscreen) ++ if config.val.content.desktop_fullscreen or self.config_state_before_fullscreen: ++ self.setWindowState(self.window_state_before_fullscreen) + log.misc.debug('on: {}, state before fullscreen: {}'.format( + on, debug.qflags_key(Qt, self.state_before_fullscreen))) + ","If you really want to rename this, you'll also need to adjust the name in `__init__` and in other places it's used (`browser/commands.py`)." +808,"@@ -53,6 +53,7 @@ public class MapLayerMetadata implements Serializable { + // ForeignKey to DataFile + //x@ManyToOne + // For now, make this unique: Each DataFile may only have one map ++ //@OneToOne(cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}) // TODO: Figure out why this doesn't work. + @JoinColumn(nullable=false, unique=true) + private DataFile dataFile; + ","As discussed at standup, I gave up on this. Calling `DeleteMapLayerMetadataCommand` felt cleaner anyway because there might be other cleanup that needs to happen. @scolapasta and @matthew-a-dunlap plan to discuss this." +809,"@@ -84,5 +84,8 @@ func (a *action) Matches(act coretesting.Action) error { + return nil + } + ++ fmt.Printf(""EXP:%+v\n"", objExp.GetObject()) ++ fmt.Printf(""ACT:%+v\n"", objExp.GetObject()) ++ + return fmt.Errorf(""unexpected difference between actions: %s"", pretty.Diff(objExp.GetObject(), objAct.GetObject())) + }","Do we need these changes? If so, can you tidy up the messages? Looks like it might have been your testing/debugging changes " +810,"@@ -63,6 +63,9 @@ const ( + + // SecretTypeEnv is to show secret type being ENVIRONMENT_VARIABLE + SecretTypeEnv = ""ENVIRONMENT_VARIABLE"" ++ ++ // TargetLogDriver is to show secret target being ""LOG_DRIVER"", the default will be ""CONTAINER"" ++ SecretTargetLogDriver = ""LOG_DRIVER"" + ) + + // DockerConfig represents additional metadata about a container to run. It's",where is the default being set? +811,"@@ -154,7 +154,7 @@ static void found_package_cb (const char *line, + vString *name = vStringNew (); + tagEntryInfo tag; + +- vStringNCopyS (name, line + matches[1].start, matches[1].length); ++ vStringNCopyS (name, line + matches[2].start, matches[2].length); + initTagEntry (&tag, vStringValue (name), RpmSpecKinds + K_PACKAGE); + tag.extensionFields.scopeIndex = *(int *)userData; + makeTagEntry (&tag);",these changes should likely be in the next commit instead +812,"@@ -26,9 +26,12 @@ import ( + ""github.com/stretchr/testify/assert"" + ) + ++type Foobar struct { ++ Foo string ++} ++ + // TestFormat ensures the formatter and AddonTransform works as expected. + func TestFormat(t *testing.T) { +- // TODO: Add table formatter tests after implementing table formatter + for _, tc := range []struct { + name string + singleton bool","Since you have defined this struct, I would suggest to replace all exist literal structs by this." +813,"@@ -168,6 +168,7 @@ public class K9 extends Application { + private static boolean mAnimations = true; + + private static boolean mConfirmDelete = false; ++ private static boolean mConfirmMenuDiscard = true; + private static boolean mConfirmDeleteStarred = false; + private static boolean mConfirmSpam = false; + private static boolean mConfirmDeleteFromNotification = true;",The field name doesn't really capture what this option does. I think `mConfirmDiscardMessage` would be a better choice. +814,"@@ -192,6 +192,15 @@ class FileProvider extends BaseProvider + return; + } + ++ // is_file will cause a fatal error if binary content is not a string ++ if (!is_string($media->getBinaryContent())) { ++ throw new \RuntimeException(sprintf( ++ 'Invalid data provided for binary content, choose among: string, %s, %s', ++ 'Symfony\Component\HttpFoundation\File\File', ++ 'Symfony\Component\HttpFoundation\Request' ++ )); ++ } ++ + // if the binary content is a filename => convert to a valid File + if (!is_file($media->getBinaryContent())) { + throw new \RuntimeException('The file does not exist : '.$media->getBinaryContent());",what if `$media->getBinaryContent() == Symfony\Component\HttpFoundation\File\File` does `is_string()` return `true`? ping @greg0ire +815,"@@ -1065,11 +1065,9 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) { + } + } + // generate object accessors if is nested_flatbuffer ++ if (field.nested_flatbuffer) { + auto nested = field.attributes.Lookup(""nested_flatbuffer""); +- if (nested) { +- auto nested_qualified_name = +- parser_.namespaces_.back()->GetFullyQualifiedName(nested->constant); +- auto nested_type = parser_.structs_.Lookup(nested_qualified_name); ++ auto nested_type = nested->type.struct_def; + auto nested_type_name = WrapInNameSpace(*nested_type); + auto nestedMethodName = MakeCamel(field.name, lang_.first_camel_upper) + + ""As"" + nested_type_name;",maybe rather than `bool` make this field a `StructDef *` ? +816,"@@ -209,6 +209,13 @@ func (fbm *folderBlockManager) enqueueBlocksToDelete(toDelete blocksToDelete) { + fbm.blocksToDeleteChan <- toDelete + } + ++func (fbm *folderBlockManager) enqueueBlocksToDeleteAfterShortDelay( ++ toDelete blocksToDelete) { ++ fbm.blocksToDeleteWaitGroup.Add(1) ++ time.AfterFunc(10*time.Millisecond, ++ func() { fbm.blocksToDeleteChan <- toDelete }) ++} ++ + // enqueueBlocksToDeleteNoWait enqueues blocks to be deleted just like + // enqueueBlocksToDelete, except that when fbm.blocksToDeleteChan is full, it + // doesn't block, but instead spawns a goroutine to handle the sending.",Shall we maybe put this in a `const` like `backgroundTaskTimeout`? +817,"@@ -272,6 +272,11 @@ namespace Datadog.Trace.TestHelpers + ctx.Response.OutputStream.Write(buffer, 0, buffer.Length); + ctx.Response.Close(); + } ++ catch (InvalidOperationException) ++ { ++ // this can occur when setting Response.ContentLength64, with the framework claiming that the response has already been submitted ++ // for now ignore, and we'll see if this introduces downstream issues ++ } + catch (HttpListenerException) + { + // listener was stopped,",CI is complaining about this. +818,"@@ -31,6 +31,14 @@ import java.util.Date; + */ + public class DefaultHistoryRemovalTimeProvider implements HistoryRemovalTimeProvider { + ++ public static Date determineRemovalTime(Date initTime, Integer timeToLive) { ++ Calendar removalTime = Calendar.getInstance(); ++ removalTime.setTime(initTime); ++ removalTime.add(Calendar.DATE, timeToLive); ++ ++ return removalTime.getTime(); ++ } ++ + public Date calculateRemovalTime(HistoricProcessInstanceEventEntity historicRootProcessInstance, ProcessDefinition processDefinition) { + + Integer historyTimeToLive = processDefinition.getHistoryTimeToLive();",Let's only change a file if it is really necessary. Such a change does not bring much value and makes it harder to find the original commit in which the method was introduced. +819,"@@ -210,6 +210,14 @@ class ImageExtension extends Twig_Extension + $htmlAttributes = $attributes; + unset($htmlAttributes['type'], $htmlAttributes['size']); + ++ $useLazyLoading = array_key_exists('lazy', $attributes) ? (bool)$attributes['lazy'] : true; ++ $isAttributeClassExistsAndNotEmpty = array_key_exists('class', $attributes) && $attributes['class'] !== ''; ++ $htmlAttributes['class'] = sprintf( ++ '%s%s', ++ $useLazyLoading ? 'lazy' : '', ++ $isAttributeClassExistsAndNotEmpty ? ' ' . $attributes['class'] : '' ++ ); ++ + return $this->templating->render('@ShopsysFramework/Common/image.html.twig', [ + 'attr' => $htmlAttributes, + 'additionalImagesData' => $additionalImagesData,","I would prefer to set up space between classes in format pattern, `%s %s` and then use `trim()` to remove unnecessary whitespaces. This will also solve stripping whitespaces from the beginning and end of a string `$attributes['class']`" +820,"@@ -22,9 +22,13 @@ AdminJobExecutor::AdminJobExecutor(Sentence *sentence, + + void AdminJobExecutor::execute() { + LOG(INFO) << __func__ << "" enter""; +- auto opEnum = toAdminJobOp(sentence_->getType()); ++ auto optOpEnum = toAdminJobOp(sentence_->getType()); ++ if (!optOpEnum) { ++ LOG(ERROR) << ""unknown setence type["" << sentence_->getType() <<""]""; ++ } + auto paras = sentence_->getParas(); + ++ auto opEnum = *optOpEnum; + if (opNeedsSpace(opEnum)) { + auto status = checkIfGraphSpaceChosen(); + if (!status.ok()) {",when Op is illegal should return here? +821,"@@ -447,8 +447,6 @@ public class FlowRunnerManager implements EventListener, + } catch (IOException e) { + logger.error(e); + } +- +- installedVersions.remove(versionKey); + } + } + }",don't we need to remove the project version from installedVersions? +822,"@@ -47,6 +47,12 @@ module Selenium + @bridge.send_command(cmd: cmd, params: params) + end + ++ def print_page(**options) ++ options[:page_ranges] &&= Array(options[:page_ranges]) ++ ++ bridge.print_page(options) ++ end ++ + private + + def debugger_address",the bridge here isn't defined as an accessor / reader to try mask it better. So you need to directly call the iVar `@bridge` here. +823,"@@ -51,7 +51,10 @@ func (s *DaemonServer) FlushIPSets(ctx context.Context, req *pb.IPSetsRequest) ( + ipset := ipset + s.IPSetLocker.Lock(ipset.Name) + err := flushIPSet(ctx, req.EnterNS, pid, ipset) +- s.IPSetLocker.Unlock(ipset.Name) ++ if err != nil { ++ return nil, err ++ } ++ err = s.IPSetLocker.Unlock(ipset.Name) + if err != nil { + return nil, err + }",This is intended. Pls revert this. +824,"@@ -68,7 +68,7 @@ interface RedBlackTree extends Iterable { + + static > RedBlackTree ofAll(Iterable values) { + Objects.requireNonNull(values, ""values is null""); +- return ofAll((Comparator & Serializable) T::compareTo, values); ++ return ofAll(Comparators.naturalComparator(), values); + } + + @SuppressWarnings(""unchecked"")","Something wrong with cast to `(Comparator<> & Serializable)`, need to be investigated" +825,"@@ -217,15 +217,10 @@ export default class App extends Component { + + // eslint-disable-next-line no-unused-vars + handleClickSearch = (_, { suggestionValue, method }) => { +- const { packages } = this.state; + switch(method) { + case 'click': +- window.location.href = getDetailPageURL(suggestionValue); +- break; + case 'enter': +- this.setState({ +- filteredPackages: packages.filter(pkg => pkg.label.match(suggestionValue)) +- }); ++ window.location.href = getDetailPageURL(suggestionValue); + break; + } + }","I think we need this. Not sure, I'll test." +826,"@@ -83,7 +83,6 @@ module Beaker + host['user'] = 'google_compute' + + disable_se_linux(host, @options) +- disable_iptables(host, @options) + copy_ssh_to_root(host, @options) + enable_root_login(host, @options) + host['user'] = default_user","I'm going to need to check if google compute requires these steps in this order, or if you can disable iptables after the fact." +827,"@@ -2,6 +2,7 @@ + // sources: + // build/static/charts/traefik-10.3.001.tgz + // build/static/charts/traefik-crd-10.3.001.tgz ++//go:build !no_stage + // +build !no_stage + + package static",Did go change their tags with the new version? +828,"@@ -330,11 +330,15 @@ func (s *Server) newEndpointsServer(ctx context.Context, catalog catalog.Catalog + } + + func (s *Server) newBundleManager(cat catalog.Catalog, metrics telemetry.Metrics) *bundle_client.Manager { ++ log := s.config.Log.WithField(telemetry.SubsystemName, ""bundle_client"") + return bundle_client.NewManager(bundle_client.ManagerConfig{ +- Log: s.config.Log.WithField(telemetry.SubsystemName, ""bundle_client""), ++ Log: log, + Metrics: metrics, + DataStore: cat.GetDataStore(), +- Source: bundle_client.TrustDomainConfigMap(s.config.Federation.FederatesWith), ++ Source: bundle_client.MergeTrustDomainConfigSources( ++ bundle_client.TrustDomainConfigMap(s.config.Federation.FederatesWith), ++ bundle_client.DataStoreTrustDomainConfigSource(log, cat.GetDataStore()), ++ ), + }) + } + ","I don't recall what we decided here in terms of which source would get priority. As written, the static configuration will overwrite datastore results." +829,"@@ -192,7 +192,7 @@ func replaceSequenceLabel(state *core.BuildState, target *core.BuildTarget, labe + } + + func checkAndReplaceSequence(state *core.BuildState, target, dep *core.BuildTarget, in string, runnable, multiple, dir, outPrefix, hash, test, allOutputs, tool bool) string { +- if allOutputs && !multiple && len(dep.Outputs()) != 1 { ++ if allOutputs && !multiple && len(dep.Outputs()) > 1 { + // Label must have only one output. + panic(fmt.Sprintf(""Rule %s can't use %s; %s has multiple outputs."", target.Label, in, dep.Label)) + } else if runnable && !dep.IsBinary {",I think it should still panic for when there are no outputs; might be nice to special-case that though so the message is more explicit. +830,"@@ -110,12 +110,14 @@ public class SolrMetricManager { + + public static final int DEFAULT_CLOUD_REPORTER_PERIOD = 60; + +- private MetricRegistry.MetricSupplier counterSupplier; +- private MetricRegistry.MetricSupplier meterSupplier; +- private MetricRegistry.MetricSupplier timerSupplier; +- private MetricRegistry.MetricSupplier histogramSupplier; ++ private final MetricsConfig metricsConfig; ++ private final MetricRegistry.MetricSupplier counterSupplier; ++ private final MetricRegistry.MetricSupplier meterSupplier; ++ private final MetricRegistry.MetricSupplier timerSupplier; ++ private final MetricRegistry.MetricSupplier histogramSupplier; + + public SolrMetricManager() { ++ metricsConfig = new MetricsConfig.MetricsConfigBuilder().build(); + counterSupplier = MetricSuppliers.counterSupplier(null, null); + meterSupplier = MetricSuppliers.meterSupplier(null, null); + timerSupplier = MetricSuppliers.timerSupplier(null, null);",*NULL_DEREFERENCE:* object `null` is dereferenced by call to `meterSupplier(...)` at line 122. +831,"@@ -60,12 +60,7 @@ function _command(server, ns, cmd, options, callback) { + finalCmd.$clusterTime = clusterTime; + } + +- if ( +- isSharded(server) && +- !shouldUseOpMsg && +- readPreference && +- readPreference.preference !== 'primary' +- ) { ++ if (isSharded(server) && !shouldUseOpMsg && readPreference && readPreference.mode !== 'primary') { + finalCmd = { + $query: finalCmd, + $readPreference: readPreference.toJSON()",switch over to .mode +832,"@@ -125,7 +125,7 @@ describe('HiddenColumns', () => { + }); + + it('should return correct visual indexes when columns sequence is non-contiguous ' + +- '(force desync between physical and visual indexes)', () => { ++ '(force desync between physical and visual indexes)', () => { + const hot = handsontable({ + data: Handsontable.helper.createSpreadsheetData(1, 10), + colHeaders: true,",I guess your IDE did some auto-fixing here +833,"@@ -32,6 +32,7 @@ import org.apache.lucene.search.BooleanClause; + import org.apache.lucene.search.BooleanQuery; + import org.apache.lucene.search.DisjunctionMaxQuery; + import org.apache.lucene.search.FuzzyQuery; ++import org.apache.lucene.search.PhraseQuery; + import org.apache.lucene.search.TermQuery; + + public class TestRamUsageEstimator extends LuceneTestCase {",This is an unused import failing recommit still. +834,"@@ -133,8 +133,12 @@ module Beaker + #move to the host + logger.debug ""Using scp to transfer #{source_path} to #{target_path}"" + scp_to host, source_path, target_module_dir, {:ignore => ignore_list} ++ + #rename to the selected module name, if not correct + cur_path = File.join(target_module_dir, source_name) ++ if host.is_powershell? #make sure our slashes are correct ++ cur_path = cur_path.gsub(/\//,'\\') ++ end + host.mv cur_path, target_path unless cur_path == target_path + when 'rsync' + logger.debug ""Using rsync to transfer #{source_path} to #{target_path}""","I'm concerned that we're conflating multiple things here. There are 2 things that Beaker should really care about: - Network transport - i.e. `ssh` vs `winrm` - Interpreter - i.e. `bash`, `cmd`, `powershell`, etc The problem is that @cowofevil is running Bitvise SSH, and he assumed we should be setting `is_cygwin: false` in node definitions. But that doesn't really accurately convey what we care about, and since Beaker doesn't appear to track network transport apart from interpreter, we end up in a strange state. `is_cygwin: false` appears to end up setting `is_powershell?` to `true`, which IMHO is not accurate or appropriate. Bitvise templates use `ssh` (like Cygwin), but the interpreter used is `cmd`, not `powershell`." +835,"@@ -52,6 +52,6 @@ + <%= tinymce :content_css => asset_path('application.css') %> + + +-
++
"" style=""display:none""> +
    +
    ",I think this is ok for now. This ties into the larger issue of the site not having a consistent method for relaying form input errors. Please make sure the focus gets set on the close button when the dialog opens. +836,"@@ -44,9 +44,9 @@ const COLUMN_SIZE_MAP_NAME = 'autoColumnSize'; + * autoColumnSize: {syncLimit: '40%'}, + * ``` + * +- * The plugin uses {@link GhostTable} and {@link SamplesGenerator} for calculations. +- * First, {@link SamplesGenerator} prepares samples of data with its coordinates. +- * Next {@link GhostTable} uses coordinates to get cells' renderers and append all to the DOM through DocumentFragment. ++ * The plugin uses GhostTable and SamplesGenerator for calculations. ++ * First, SamplesGenerator prepares samples of data with its coordinates. ++ * Next GhostTable uses coordinates to get cells' renderers and append all to the DOM through DocumentFragment. + * + * Sampling accepts additional options: + * - *samplingRatio* - Defines how many samples for the same length will be used to calculate. Default is `3`.",Should these link be removed? +837,"@@ -217,11 +217,12 @@ class TabbedBrowser(tabwidget.TabWidget): + for tab in self.widgets(): + self._remove_tab(tab) + +- def close_tab(self, tab): ++ def close_tab(self, tab, add_undo=True): + """"""Close a tab. + + Args: + tab: The QWebView to be closed. ++ add_undo: Whether the tab close can be undone. + """""" + last_close = config.get('tabs', 'last-close') + count = self.count()",Please make this a keyword-only argument by adding a `*` argument before `add_undo`. +838,"@@ -201,6 +201,13 @@ var eventStreamWriterTestTmpl = template.Must( + {{- end }} + } + ++ var marshalers request.HandlerList ++ marshalers.PushBackNamed({{ $.API.ProtocolPackage }}.BuildHandler) ++ payloadMarshaler := protocol.HandlerPayloadMarshal{ ++ Marshalers: marshalers, ++ } ++ _ = payloadMarshaler ++ + eventMsgs := []eventstream.Message{ + {{- range $idx, $event := $.InputStream.Events }} + {{- template ""set event message"" Map ""idx"" $idx ""parentShape"" $event.Shape ""eventName"" $event.Name }}",didn't quite follow what this code block is doing. +839,"@@ -1071,6 +1071,12 @@ define([""playbackManager"", ""dom"", ""inputManager"", ""datetime"", ""itemHelper"", ""med + } + + function onWindowKeyDown(e) { ++ // FIXME: Conflicts with keyboard navigation ++ // FIXME: Then the keyboard is completely ignored. Need another solution. ++ if (layoutManager.tv) { ++ return void showOsd(); ++ } ++ + if (!currentVisibleMenu && 32 === e.keyCode) { + playbackManager.playPause(currentPlayer); + return void showOsd();","this doesn't sound pretty... I would rather we have a proper navigation for all modes - AFAIK TV remote navigation is very similar to normal keyboard, but maybe it just uses another key codes - those should be extracted in a single file and defined there depending on context then" +840,"@@ -205,4 +205,17 @@ function patchDOMElement(dom, newVNode, internal, globalContext, commitQueue) { + dom.firstChild + ); + } ++ ++ if ('value' in newProps && dom._isControlled) { ++ dom._prevValue = newProps.value; ++ ++ if (newProps.value !== dom.value) { ++ setProperty(dom, 'value', i, oldProps.value, 0); ++ } ++ } else if ('checked' in newProps && dom._isControlled) { ++ dom._prevValue = newProps.checked; ++ if (newProps.checked !== dom.checked) { ++ setProperty(dom, 'checked', i, oldProps.checked, 0); ++ } ++ } + }","After diffing the children we check whether the value got out of sync, if it did we update it. We also update the `_prevValue` to prepare for the next event hitting our controlled component" +841,"@@ -2,6 +2,8 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + ++// Package node provides the glue-code needed in order ++// to start a Bee node. + package node + + import (","It provides a type called Node which is a fully functional bee client. This package is where the dependencies are injected. It is not just a glue-code, it is concept of node." +842,"@@ -330,6 +330,8 @@ class ConfigManager(QObject): + CHANGED_OPTIONS = { + ('content', 'cookies-accept'): + _get_value_transformer('default', 'no-3rdparty'), ++ ('storage', 'download-directory'): ++ _get_value_transformer('', '%'), + } + + changed = pyqtSignal(str, str)","I think this will change `''` to `'%'` unconditionally, i.e. there'll be no way to set `''` anymore. This should really only be used for values which make no sense anymore." +843,"@@ -88,6 +88,13 @@ public interface Table { + */ + Map sortOrders(); + ++ /** ++ * Return the {@link RowKey row key} for this table. ++ * ++ * @return this table's row key. ++ */ ++ RowKey rowKey(); ++ + /** + * Return a map of string properties for this table. + *",Nit: this table's row key map -> this table's row keys map +844,"@@ -87,7 +87,7 @@ void proj_assign_context( PJ* pj, PJ_CONTEXT *ctx ) + pj_ctx pj_ctx::createDefault() + { + pj_ctx ctx; +- ctx.debug_level = PJ_LOG_ERROR; ++ ctx.debug_level = PJ_LOG_NONE; + ctx.logger = pj_stderr_logger; + NS_PROJ::FileManager::fillDefaultNetworkInterface(&ctx); + ",this change should be reverted +845,"@@ -26,8 +26,10 @@ __copyright__ = ""Copyright 2014-2018 Florian Bruhin (The Compiler)"" + __license__ = ""GPL"" + __maintainer__ = __author__ + __email__ = ""mail@qutebrowser.org"" +-__version_info__ = (1, 5, 0) +-__version__ = '.'.join(str(e) for e in __version_info__) ++__version__ = ""1.5.0"" ++__version_info__ = [int(part) for part in __version__.split('.')] + __description__ = ""A keyboard-driven, vim-like browser based on PyQt5."" + + basedir = os.path.dirname(os.path.realpath(__file__)) ++appdata_path = os.path.join(os.path.dirname(basedir), ""misc"", ++ ""qutebrowser.appdata.xml"")","I'm a bit confused about the `os.path.dirname(basedir)` here - is this just to get to the parent directory? Either way, I think I'd prefer just having this in `update_version.py` as it's not needed in qutebrowser itself." +846,"@@ -750,8 +750,8 @@ func TestConfigCheck(t *testing.T) { + http_port = 8222 + `, + err: errors.New(`Duplicate user ""foo"" detected`), +- errorLine: 6, +- errorPos: 21, ++ errorLine: 5, ++ errorPos: 19, + }, + { + name: ""when accounts block imports are not a list"",",Revert this change and see below why... +847,"@@ -1,6 +1,6 @@ + _base_ = [ + '../_base_/models/cascade_mask_rcnn_r50_fpn.py', +- '../_base_/datasets/coco_instance.py', ++ '../_base_/datasets/lvis_v1_instance.py', + '../_base_/schedules/schedule_2x.py', '../_base_/default_runtime.py' + ] + ",Should not switch to `lvis_v1_instance` here because that base config uses ClassBalancedDataset to oversample the data. +848,"@@ -70,7 +70,7 @@ public class NodeOptions { + Capabilities caps = info.getCanonicalCapabilities(); + builders.stream() + .filter(builder -> builder.score(caps) > 0) +- .peek(builder -> LOG.info(String.format(""Adding %s %d times"", caps, info.getMaximumSimultaneousSessions()))) ++ .peek(builder -> LOG.finest(String.format(""Adding %s %d times"", caps, info.getMaximumSimultaneousSessions()))) + .forEach(builder -> { + DriverService.Builder freePortBuilder = builder.usingAnyFreePort(); + ",This is an informational message that allows someone to read the console output and understand how the grid node is configured. Please leave. +849,"@@ -52,6 +52,9 @@ type Alert interface { + // GetKvdbInstance. + GetKvdbInstance() kvdb.Kvdb + ++ // RaiseSingleton raises a singleton alert. ++ RaiseSingleton(alert *api.Alert) error ++ + // Raise raises an Alert. + Raise(alert *api.Alert) error + ",This doesn't make sense to me. What does RaiseSingleton mean? To me it sounds like a single object is being.. raised? Not sure. +850,"@@ -45,6 +45,7 @@ public class JavaProcessJobTest { + private JavaProcessJob job = null; + private Props props = null; + private Logger log = Logger.getLogger(JavaProcessJob.class); ++ private AllJobExecutorTests jobExecutorTests = null; + + private static String classPaths; + ","What's the benefit of having jobExecutorTests as a member variable? What do you think about making the method static? Afterall, it is a stateless method." +851,"@@ -12,6 +12,7 @@ const mdUsageStr = `Usage: + + The possible subcommands are: + dump Dump metadata objects ++ check Check metadata objects and their associated blocks for errors + + ` + ","This looks like it's only downloading things, not really checking their true validity. Especially for the MD object. Should we call `BareRootMetadata.IsValidAndSigned()` in `mdGet`?" +852,"@@ -136,6 +136,17 @@ void image_data_reader::load() { + select_subset_of_data(); + } + ++void image_data_reader::setup() { ++ generic_data_reader::setup(); ++ ++ using InputBuf_T = lbann::cv_image_type; ++ auto cvMat = cv::Mat(1, get_linearized_data_size(), InputBuf_T::T(1)); ++ m_thread_cv_buffer.resize(omp_get_max_threads()); ++ for(int tid = 0; tid < omp_get_max_threads(); ++tid) { ++ m_thread_cv_buffer[tid] = cvMat.clone(); ++ } ++} ++ + std::vector image_data_reader::get_image_list_of_current_mb() const { + std::vector ret; + ret.reserve(m_mini_batch_size);","Nikoli, I believe that this addresses your concern. One question for you or Jae-Seung is if any allocation from the clone is properly cleaned up when the vector is destroyed. I believe that it should." +853,"@@ -48,6 +48,8 @@ const ( + KindLambdaApp Kind = ""LambdaApp"" + // KindCloudRunApp represents deployment configuration for a CloudRun application. + KindCloudRunApp Kind = ""CloudRunApp"" ++ // KindEcsApp represents deployment configuration for an AWS ECS. ++ KindEcsApp Kind = ""EcsApp"" + // KindSealedSecret represents a sealed secret. + KindSealedSecret Kind = ""SealedSecret"" + )",should be `ECSApp` +854,"@@ -539,7 +539,13 @@ class WebElement(object): + @property + def rect(self): + """"""A dictionary with the size and location of the element."""""" +- return self._execute(Command.GET_ELEMENT_RECT)['value'] ++ if self._w3c: ++ return self._execute(Command.GET_ELEMENT_RECT)['value'] ++ else: ++ rect = self.size.copy() ++ rect.update(self.location) ++ return rect ++ + + @property + def screenshot_as_base64(self):",flake8 is going to fail on this having 2 lines +855,"@@ -15,7 +15,6 @@ package podfailure + + import ( + ""context"" +- ""errors"" + ""fmt"" + ""time"" + ",should we make a dir named controllers/scheduler/podchaos +856,"@@ -50,9 +50,9 @@ import ( + ) + + const ( +- //KeyNode represents the key values used for specifying the Node Affinity ++ //KeyNodeHostname represents the key values used for specifying the Node Affinity + // based on the hostname +- KeyNode = ""kubernetes.io/hostname"" ++ KeyNodeHostname = ""kubernetes.io/hostname"" + ) + + // NewProvisioner will create a new Provisioner object and initialize",there seems to be one KeyNode in kubernetes.go of PV.. would it make sense to use it? +857,"@@ -22,12 +22,12 @@ import ( + ""fmt"" + ""time"" + ++ ""github.com/mysteriumnetwork/node/cmd/commands"" ++ + ""github.com/mysteriumnetwork/node/cmd/commands/cli/clio"" + ""github.com/mysteriumnetwork/node/config"" +- ""github.com/mysteriumnetwork/node/config/urfavecli/clicontext"" + ""github.com/mysteriumnetwork/node/core/connection"" + ""github.com/mysteriumnetwork/node/core/connection/connectionstate"" +- ""github.com/mysteriumnetwork/node/core/node"" + ""github.com/mysteriumnetwork/node/datasize"" + ""github.com/mysteriumnetwork/node/identity/registry"" + ""github.com/mysteriumnetwork/node/metadata""",Im gonna be a little annoying here but did you configure your linter correctly? This empty line should not be here. Maybe go to settings and check if `goimports` is enabled? +858,"@@ -122,6 +122,7 @@ public class EmojiPlugin extends Plugin + case FRIENDSCHAT: + case PRIVATECHAT: + case PRIVATECHATOUT: ++ case MODPRIVATECHAT: + break; + default: + return;",Don't think this belongs in this pr +859,"@@ -206,6 +206,16 @@ func (d *Dispatcher) Inbounds() Inbounds { + return inbounds + } + ++// Outbounds returns a copy of the map of outbounds for this RPC object. ++// The outbounds are already wrapped with middleware ++func (d *Dispatcher) Outbounds() Outbounds { ++ outbounds := make(Outbounds, len(d.outbounds)) ++ for k, v := range d.outbounds { ++ outbounds[k] = v ++ } ++ return outbounds ++} ++ + // ClientConfig provides the configuration needed to talk to the given + // service through an outboundKey. This configuration may be directly + // passed into encoding-specific RPC clients.","We can assert on the existence of Outbounds through ClientConfig calls right? Since this is only for tests, do we need this function?" +860,"@@ -37,14 +37,13 @@ namespace MvvmCross.Core.ViewModels + + public interface IMvxViewModel : IMvxViewModel where TParameter : class + { +- Task Initialize(TParameter parameter); ++ void Declare(TParameter parameter); + } + + //TODO: Can we keep the IMvxViewModel syntax here? Compiler complains + public interface IMvxViewModelResult : IMvxViewModel where TResult : class + { +- void SetClose(TaskCompletionSource tcs, CancellationToken cancellationToken); +- Task Close(TResult result); ++ TaskCompletionSource CloseCompletionSource { get; set; } + } + + public interface IMvxViewModel : IMvxViewModel, IMvxViewModelResult where TParameter : class where TResult : class",@martijn00 so this PR introduces a new ViewModel lifecyle method? It isn't in the PR description/any new docs +861,"@@ -89,6 +89,13 @@ class SingleStageDetector(BaseDetector): + Returns: + dict[str, Tensor]: A dictionary of loss components. + """""" ++ # NOTE the batched image size information may be useful, e.g. ++ # in DETR, this is needed for the construction of masks, which is ++ # then used for the transformer_head. ++ input_img_shape = tuple(img.size()[-2:]) ++ for img_meta in img_metas: ++ img_meta['input_img_shape'] = input_img_shape ++ + x = self.extract_feat(img) + losses = self.bbox_head.forward_train(x, img_metas, gt_bboxes, + gt_labels, gt_bboxes_ignore)",Are these modification duplicate? Or should we move it into base detector. +862,"@@ -35,7 +35,7 @@ public class DirectAcyclicGraphSeed { + } + }); + +- public static byte[] dagSeed(final long block) { ++ private static byte[] dagSeed(final long block) { + final byte[] seed = new byte[32]; + if (Long.compareUnsigned(block, EPOCH_LENGTH) >= 0) { + final MessageDigest keccak256 = KECCAK_256.get();",Since this is private and single use it should be un-wrapped inside of the two-arg dagSeed method. +863,"@@ -160,11 +160,10 @@ abstract class Tx_Solr_PluginBase_PluginBase extends tslib_pibase { + * @param array $configuration configuration array as provided by the TYPO3 core + */ + protected function initialize($configuration) { +- $this->conf = $configuration; +- +- $this->conf = t3lib_div::array_merge_recursive_overrule( +- $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_solr.'], +- $this->conf ++ $this->conf = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_solr.']; ++ \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule( ++ $this->conf, ++ $configuration + ); + + $this->pi_setPiVarDefaults();",why the order change? Also for the next chunk. (I understand the result will be the same though) +864,"@@ -42,7 +42,9 @@ type FuncDef struct { + // Not part of the grammar. Used to indicate internal targets that can only + // be called using keyword arguments. + KeywordsOnly bool +- IsPrivate bool ++ // allowed return types of the FuncDef ++ Returns []string ++ IsPrivate bool + } + + // A ForStatement implements the 'for' statement.",I wonder if this should just be a single `string`? We don't have any cases where we return different types and it would make the parser simpler to just read a single identifier. +865,"@@ -125,7 +125,7 @@ abstract class BaseDataReader implements Closeable { + + protected InputFile getInputFile(FileScanTask task) { + Preconditions.checkArgument(!task.isDataTask(), ""Invalid task type""); +- return inputFiles.get(task.file().path().toString()); ++ return getInputFile(task.file().path().toString()); + } + + protected InputFile getInputFile(String location) {",I don't think this needs to change. Can you go back to the previous implementation? +866,"@@ -32,7 +32,7 @@ from jinja2 import PackageLoader + + import molecule.utilities as utilities + import molecule.validators as validators +-from provisioners import Ansible ++from molecule.core import Molecule + + + class Commands(object):","Bump it 2 lines higher, 'c' > 'u'." +867,"@@ -0,0 +1,11 @@ ++/** ++ * Copyright @ 2018-present. All rights reserved by Vesoft Inc. ++ * Author: Fenglin Hou ++ */ ++#include ""parser/AstTypes.h"" ++ ++namespace vesoft { ++ ++ ++ ++}",Please do not add author here +868,"@@ -4,6 +4,7 @@ import ( + ""database/sql"" + ""encoding/hex"" + ++ ""github.com/iotexproject/iotex-core/action"" + ""github.com/iotexproject/iotex-core/blockchain"" + ""github.com/iotexproject/iotex-core/config"" + ""github.com/iotexproject/iotex-core/db/rds""","Similarly, we should be able to persist action uniformly" +869,"@@ -1,3 +1,8 @@ ++#This prevents caching via the browser ++#in testing mode ++module ActionController::ConditionalGet ++ def expires_in(*args) ; end ++end + Workshops::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + ","I think i'd prefer this override to be in the test helper instead, if that's possible?" +870,"@@ -134,6 +134,13 @@ func Untar(source string, dest string, extractionDir string) error { + case tar.TypeReg: + fallthrough + case tar.TypeRegA: ++ // Always ensure the directory is created before trying to move the file. ++ fullPathDir := filepath.Dir(fullPath) ++ err = os.MkdirAll(fullPathDir, 0755) ++ if err != nil { ++ return err ++ } ++ + // For a regular file, create and copy the file. + exFile, err := os.Create(fullPath) + if err != nil {",This would be better with context added via wrapping or fmt.errorf() +871,"@@ -0,0 +1,19 @@ ++// Copyright 2020 Google Inc. All Rights Reserved. ++// ++// 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 assert provides convenience functions that help a method or constructor check whether ++// it was invoked correctly (whether its preconditions have been met). ++// ++// When the assertion fails, a panic occurs, allowing bugs to be found in a fail-fast manner. ++package assert",What's the purpose of this file? +872,"@@ -616,12 +616,14 @@ public class PasscodeManager { + */ + public void setPasscodeLength(Context ctx, int passcodeLength) { + if (passcodeLength > this.passcodeLength) { +- if (hasStoredPasscode(ctx)) { ++ if (hasStoredPasscode(ctx) && passcodeLengthKnown) { + this.passcodeChangeRequired = true; + } ++ ++ this.passcodeLength = passcodeLength; + } +- this.passcodeLength = passcodeLength; +- this.passcodeLengthKnown = true; ++ ++ this.passcodeLengthKnown = true; + storeMobilePolicy(ctx); + } + ",@bhariharan Why was passcode length requirement allowed to be lowered? +873,"@@ -6,14 +6,6 @@ import ( + ""flag"" + ""io/ioutil"" + ""log"" +- +- ""github.com/aws/aws-sdk-go/aws"" +- ""github.com/aws/aws-sdk-go/aws/credentials"" +- ""github.com/aws/aws-sdk-go/aws/session"" +- ""github.com/google/go-cloud/blob"" +- ""github.com/google/go-cloud/blob/gcsblob"" +- ""github.com/google/go-cloud/blob/s3blob"" +- ""github.com/google/go-cloud/gcp"" + ) + + const bucketName = ""my-cool-bucket""","This file needs a license header, too. Sorry I didn't catch that earlier." +874,"@@ -289,7 +289,7 @@ func main() { + } + } + +- err = s.Initialize(cfg, phonebookAddresses) ++ err = s.Initialize(cfg, phonebookAddresses, string(genesisText[:])) + if err != nil { + fmt.Fprintln(os.Stderr, err) + log.Error(err)",probably don't need `[:]` why not reference into `github.com/algorand/go-algorand/daemon/algod/api/server/lib` here and skip bouncing off daemon/algod/server.go ? +875,"@@ -86,8 +86,13 @@ public: + const table& y_data, + const table& result_values) { + auto reference = compute_reference(scale, shift, x_data, y_data); ++ const table reference_table = dal::detail::homogen_table_builder{} ++ .reset(reference.get_array(), ++ reference.get_row_count(), ++ reference.get_column_count()) ++ .build(); + const double tol = te::get_tolerance(3e-4, 1e-9); +- const double diff = la::l_inf_norm(reference, la::matrix::wrap(result_values)); ++ const double diff = te::abs_error(reference_table, result_values); + CHECK(diff < tol); + } + ",Why reference is converted to table? +876,"@@ -347,6 +347,19 @@ func (s *DataStore) ListRegistrationEntries(ctx context.Context, + s.mu.Lock() + defer s.mu.Unlock() + ++ // no pagination allow for this fake, for now it return only one page ++ if req.Pagination != nil { ++ if req.Pagination.Token == 0 { ++ req.Pagination.Token = 1 ++ } else { ++ // for now only 1 page is returned ++ return &datastore.ListRegistrationEntriesResponse{ ++ Entries: []*common.RegistrationEntry{}, ++ Pagination: req.Pagination, ++ }, nil ++ } ++ } ++ + // add the registration entries to the map + entriesSet := make(map[string]*common.RegistrationEntry) + for _, entry := range s.registrationEntries {",should we implement pagination in the fake datastore so the server startup code that paginates entries for trust domain validation can be tested? +877,"@@ -15,6 +15,12 @@ func Compile(scope Scope, f *semantic.FunctionExpression, in semantic.MonoType) + return nil, errors.Newf(codes.Invalid, ""function input must be an object @ %v"", f.Location()) + } + ++ // If the function is vectorizable, `f.Vectorized` will be populated, and ++ // we should use the FunctionExpression it points to instead of `f` ++ if f.Vectorized != nil { ++ f = f.Vectorized ++ } ++ + // Retrieve the function argument types and create an object type from them. + fnType := f.TypeOf() + argN, err := fnType.NumArguments()",What mechanism will be exposed so the caller knows they're using the vectorized version? +878,"@@ -20,9 +20,9 @@ class TopicsController < ApplicationController + @topic = build_new_topic + respond_to do |format| + if verify_recaptcha(model: @topic) && @topic.save +- format.html { redirect_to forum_path(@forum), flash: { success: t('.success') } } ++ format.html { redirect_to forum_path(@forum), notice: t('.success') } + else +- format.html { redirect_to forum_path(@forum), flash: { error: t('.error') } } ++ format.html { render :new } + end + end + end",Can we remove respond_to block its not required here +879,"@@ -23,12 +23,13 @@ + #include ""oneapi/dal/algo/jaccard.hpp"" + #include ""oneapi/dal/graph/service_functions.hpp"" + #include ""oneapi/dal/graph/undirected_adjacency_vector_graph.hpp"" +-#include ""oneapi/dal/io/graph_csv_data_source.hpp"" +-#include ""oneapi/dal/io/load_graph.hpp"" ++#include ""oneapi/dal/io/csv.hpp"" + #include ""oneapi/dal/table/homogen.hpp"" + + namespace dal = oneapi::dal; + ++using namespace dal; ++ + /// Computes Jaccard similarity coefficients for the graph. The upper triangular + /// matrix is processed only as it is symmetic for undirected graph. + ///","Do not do that even in example, we demonstrate bad practice" +880,"@@ -202,7 +202,13 @@ module Beaker + #Examine the host system to determine the architecture + #@return [Boolean] true if x86_64, false otherwise + def determine_if_x86_64 +- result = exec(Beaker::Command.new(""arch | grep x86_64""), :acceptable_exit_codes => (0...127)) ++ if self['is_cygwin'].nil? or self['is_cygwin'] == true ++ command = Beaker::Command.new(""arch | grep x86_64"") ++ else ++ command = Beaker::Command.new(""echo '' | wmic os get osarchitecture | FindStr 64-bit"") ++ end ++ ++ result = exec(command, :acceptable_exit_codes => (0...127)) + result.exit_code == 0 + end + ","Hm, taking a second look over this, this is why we have the object inheritance structure that we do. This could be divided up by having a custom determine_if_x86_64 in the pswindows/exec hosts and then a default method in hosts.rb. That way all the custom ps windows work is in a single location." +881,"@@ -84,11 +84,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests + [InlineData(null, new byte[0])] + public void EncodesAsAscii(string input, byte[] expected) + { +- var writerBuffer = _pipe.Writer; +- var writer = new BufferWriter(writerBuffer); ++ var pipeWriter = _pipe.Writer; ++ var writer = new BufferWriter(pipeWriter); + writer.WriteAsciiNoValidation(input); + writer.Commit(); +- writerBuffer.FlushAsync().GetAwaiter().GetResult(); ++ pipeWriter.FlushAsync().GetAwaiter().GetResult(); ++ pipeWriter.Complete(); ++ + var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); + + if (expected.Length > 0)",We have to `.Complete` now because of empty/null string test cases. +882,"@@ -166,7 +166,7 @@ module Beaker + def scp_to source, target, options = {}, dry_run = false + return if dry_run + +- options[:recursive] = File.directory?(source) if options[:recursive].nil? ++ options[:recursive] = File.directory?(source) + options[:chunk_size] = options[:chunk_size] || 16384 + + result = Result.new(@hostname, [source, target])",Is there still a way to specify no recursion? +883,"@@ -438,6 +438,15 @@ Loop: + return w, nil + } + ++// Tool is used to communicate the tool's name ot the user. ++type Tool struct { ++ ++ // HumanReadableName is used for error messages, for example: ""image import"". ++ HumanReadableName string ++ // URISafeName is used programmatically, eg: ""image-import"" ++ URISafeName string ++} ++ + // EnvironmentSettings controls the resources that are used during tool execution. + type EnvironmentSettings struct { + // Location of workflows",How is this name being URI safe and being used programmatically related? +884,"@@ -358,14 +358,14 @@ module.exports = class ProviderView { + state = this.plugin.getPluginState() + state.selectedFolders[folderId] = { loading: false, files: files } + this.plugin.setPluginState({ selectedFolders: folders }) +- const dashboard = this.plugin.uppy.getPlugin('Dashboard') ++ + let message + if (files.length) { +- message = dashboard.i18n('folderAdded', { ++ message = this.plugin.uppy.i18n('folderAdded', { + smart_count: files.length, folder: folder.name + }) + } else { +- message = dashboard.i18n('emptyFolderAdded') ++ message = this.plugin.uppy.i18n('emptyFolderAdded') + } + this.plugin.uppy.info(message) + }).catch((e) => {","I think we have to keep this as a fallback for now, else it's a small breaking change :(" +885,"@@ -80,7 +80,7 @@ func TestOpImmediateNote(t *testing.T) { + func TestOpDocExtra(t *testing.T) { + xd := OpDocExtra(""bnz"") + require.NotEmpty(t, xd) +- xd = OpDocExtra(""+"") ++ xd = OpDocExtra(""-"") + require.Empty(t, xd) + } + ",nit: shouldn't be part of this PR. +886,"@@ -83,7 +83,7 @@ describe('Cursor Async Iterator Tests', function() { + expect(doc).to.exist; + cursor.close(); + } +- throw new Error('expected closing the cursor to break iteration'); ++ throw new MongoError('expected closing the cursor to break iteration'); + } catch (e) { + expect(e).to.be.an.instanceOf(MongoError); + }","this change looks wrong to me. I think the test is trying to signal that something went wrong by throwing the `Error` here, otherwise the `catch` below will swallow it." +887,"@@ -164,6 +164,13 @@ namespace NLog.Internal + + if (reusableBuilder != null) + { ++ if (!_layout.IsThreadAgnostic) ++ { ++ string cachedResult; ++ if (logEvent.TryGetCachedLayoutValue(_layout, out cachedResult)) ++ return cachedResult; ++ } ++ + _layout.RenderAppendBuilder(logEvent, reusableBuilder); + + if (_cachedPrevRawFileName != null && _cachedPrevRawFileName.Length == reusableBuilder.Length)","I'm doubting if this should be `if (_layout.IsThreadAgnostic)`, as ThreadAgnostic stuff could be calculated on every thread. (and thus could be lazy). non-ThreadAgnostic should be calculated on the main thread." +888,"@@ -7,14 +7,19 @@ import javafx.scene.control.ToggleGroup; + import javafx.scene.layout.HBox; + import org.phoenicis.javafx.views.common.widgets.lists.CombinedListWidget; + import org.phoenicis.javafx.views.common.widgets.lists.ListWidgetType; ++import org.slf4j.LoggerFactory; + + import java.util.Arrays; + import java.util.List; ++import java.util.Optional; ++import java.util.function.Consumer; + + /** + * Created by marc on 15.05.17. + */ + public class LeftListWidgetChooser extends HBox { ++ private final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(LeftListWidgetChooser.class); ++ + private List> listWidgets; + + private ToggleGroup toggleGroup;",Please use only `Logger` instead of `org.slf4j.Logger` +889,"@@ -326,6 +326,10 @@ void nano::block_processor::process_live (nano::transaction const & transaction_ + { + node.network.flood_block_initial (block_a); + } ++ else if (!node.flags.disable_block_processor_republishing) ++ { ++ node.network.flood_block (block_a, nano::buffer_drop_policy::no_limiter_drop); ++ } + + if (node.websocket_server && node.websocket_server->any_subscriber (nano::websocket::topic::new_unconfirmed_block)) + {","Should this be ""no limiter drop"", since this isn't an absolutely essential activity for the stability of the network?" +890,"@@ -22,8 +22,8 @@ var iam = new AWS.IAM({apiVersion: '2010-05-08'}); + + iam.deleteAccountAlias({AccountAlias: process.argv[2]}, function(err, data) { + if (err) { +- console.log(""Error"", err); ++ throw err; + } else { +- console.log(""Success"", data); ++ console.log('Account alias ' + process.argv[2] + ' deleted.'); + } + });","I updated many of the success messages, because most of these operations don't return data if they succeed. This meant many of the operations would print: `Success null` if the script ran successfully." +891,"@@ -45,6 +45,8 @@ def _test_pyx(): + stdout=devnull, stderr=subprocess.STDOUT) + except (subprocess.CalledProcessError, OSError): + return False ++ except FileNotFoundError as fnfe: ++ return False + else: + return r == 0 + ",Could you simply add it to the previous clause ? +892,"@@ -108,13 +108,10 @@ Blockly.Procedures.sortProcedureMutations_ = function(mutations) { + var procCodeA = a.getAttribute('proccode'); + var procCodeB = b.getAttribute('proccode'); + +- if (procCodeA < procCodeB) { +- return -1; +- } else if (procCodeA > procCodeB) { +- return 1; +- } else { +- return 0; +- } ++ return procCodeA.localeCompare(procCodeB, undefined, { ++ sensitivity: 'base', ++ numeric: true ++ }); + }); + + return newMutations;","@joshyrobot, I think you can just use localeCompare with only the first argument and leave the other arguments out (here and all the other lines changed). It seems to do the right thing, and then we don't have to worry about these extra options." +893,"@@ -239,6 +239,10 @@ public class ExecuteFlowAction implements TriggerAction { + } + exflow.setExecutionOptions(executionOptions); + ++ if (slaOptions != null && slaOptions.size() > 0) { ++ exflow.setSlaOptions(slaOptions); ++ } ++ + try { + logger.info(""Invoking flow "" + project.getName() + ""."" + flowName); + executorManager.submitExecutableFlow(exflow, submitUser);",@chengren311 : where does this logic move to? +894,"@@ -204,6 +204,14 @@ func (s *NodegroupService) reconcileNodegroupIAMRole() error { + } + + policies := NodegroupRolePolicies() ++ if len(s.scope.ManagedMachinePool.Spec.RoleAdditionalPolicies) > 0 { ++ if !s.scope.AllowAdditionalRoles() { ++ return ErrCannotUseAdditionalRoles ++ } ++ ++ policies = append(policies, s.scope.ManagedMachinePool.Spec.RoleAdditionalPolicies...) ++ } ++ + _, err = s.EnsurePoliciesAttached(role, aws.StringSlice(policies)) + if err != nil { + return errors.Wrapf(err, ""error ensuring policies are attached: %v"", policies)",Can we have a `nil` exception check at `s.scope.ManagedMachinePool` +895,"@@ -40,16 +40,6 @@ class Options extends \VuFind\Search\Base\Options + { + use \VuFind\Search\Options\ViewOptionsTrait; + +- /** +- * Available sort options for facets +- * +- * @var array +- */ +- protected $facetSortOptions = [ +- 'count' => 'sort_count', +- 'index' => 'sort_alphabetic' +- ]; +- + /** + * Hierarchical facets + *","Rather than deleting this, should you just reformat it so it's the `*` settings, so if nothing is configured in facets.ini, the existing default behavior continues to work?" +896,"@@ -31,11 +31,14 @@ class ManagerConfiguration { + '#collapsible' => FALSE, + ]; + foreach ($this->datastoreManager->getConfigurableProperties() as $property => $default_value) { ++ $propety_label = str_replace(""_"", "" "", $property); ++ $propety_label = ucfirst($propety_label); ++ + if ($property == ""delimiter"") { + $form['import_options'][""datastore_manager_config_{$property}""] = array( + '#type' => 'select', + // @codingStandardsIgnoreStart +- '#title' => ucfirst(t(""{$property}"")), ++ '#title' => t($propety_label), + // @codingStandardsIgnoreEnd + '#options' => array( + "","" => "","",","wrap, single line" +897,"@@ -202,6 +202,12 @@ public class JavaContextCommon { + + public abstract String getReturnType(); + ++ public String getGenericAwareReturnType() { ++ String returnType = getReturnType(); ++ if (returnType == null || returnType.isEmpty()) return ""Void""; ++ else return returnType; ++ } ++ + public abstract ImmutableList getParams(); + + public abstract ImmutableList getRequiredParams();",always use brackets for if statements +898,"@@ -34,14 +34,13 @@ namespace Datadog.Trace.ClrProfiler.Integrations.Testing + private const string NUnitTestExecutionContextType = ""NUnit.Framework.Internal.TestExecutionContext""; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(NUnitIntegration)); +- private static readonly FrameworkDescription _runtimeDescription; ++ private static readonly FrameworkDescription RuntimeDescription; + + static NUnitIntegration() + { + // Preload environment variables. + CIEnvironmentValues.DecorateSpan(null); +- +- _runtimeDescription = FrameworkDescription.Create(); ++ RuntimeDescription = FrameworkDescription.Instance; + } + + /// ",`NUnitIntegration` doesn't need to cache this anymore. +899,"@@ -210,8 +210,9 @@ EXTS_ACCESS_COUNTS = textwrap.dedent(""""""\ + eventname, + bucket, + lower(CASE +- WHEN cardinality(parts) > 2 THEN concat(element_at(parts, -2), '.', element_at(parts, -1)) +- WHEN cardinality(parts) = 2 THEN element_at(parts, -1) ++ WHEN cardinality(parts) > 2 AND lower(element_at(parts, -1)) = 'gz' ++ THEN concat(element_at(parts, -2), '.', element_at(parts, -1)) ++ WHEN cardinality(parts) >= 2 THEN element_at(parts, -1) + ELSE '' + END + ) AS ext,",Why did you change it to `>=` here? +900,"@@ -30,8 +30,11 @@ abstract class BaseAction implements Action { + String tableName = table().toString(); + if (tableName.contains(""/"")) { + return tableName + ""#"" + type; +- } else if (tableName.startsWith(""hadoop."") || tableName.startsWith(""hive."")) { +- // HiveCatalog and HadoopCatalog prepend a logical name which we need to drop for Spark 2.4 ++ } else if (tableName.startsWith(""hadoop."")) { ++ // Load a path by HadoopCatalog or HadoopTables ++ return table().location() + ""#"" + type; ++ } else if (tableName.startsWith(""hive."")) { ++ // HiveCatalog prepend a logical name which we need to drop for Spark 2.4 + return tableName.replaceFirst(""(hadoop\\.)|(hive\\.)"", """") + ""."" + type; + } else { + return tableName + ""."" + type;",Looks like this needs to be updated. There is no need to remove `hadoop.` if Hadoop tables don't use this code path. +901,"@@ -1,4 +1,5 @@ + require 'fileutils' ++require 'digest' + + module RSpec + module Core","This require isn't need anymore, right?" +902,"@@ -32,6 +32,7 @@ import ( + ""github.com/mysteriumnetwork/node/session"" + ""github.com/mysteriumnetwork/node/session/balance"" + ""github.com/mysteriumnetwork/node/session/promise"" ++ ""github.com/mysteriumnetwork/payments/crypto"" + ""github.com/pkg/errors"" + ) + ",a bit weird to see payments crypto package inside connection manager. There probably will be services not having any relation with payments that will use connection manager. Thats why probably ping-ping by itself can be useful without any relation to payments.. +903,"@@ -889,7 +889,7 @@ trait MarcAdvancedTrait + 'http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd', + 'http://www.w3.org/2001/XMLSchema-instance' + ); +- $xml->record->addAttribute('type', 'Bibliographic'); ++ $xml->record->addAttribute('type', $this->xmlType); + return $xml->record->asXML(); + } + ","I like the overall idea here, but I wonder if it would be more clear to define the property in the trait, and then set it in the constructors of the classes using the trait. Alternatively, at a bare minimum, it may be a good idea to add `?? 'Bibliographic'` here, to account for the possibility of the trait being used in a class that does not define the property at all." +904,"@@ -2,6 +2,10 @@ package protocol + + import ""time"" + ++// NonForwardSecurePacketSizeReduction is the number of bytes a non forward-secure packet has to be smaller than a forward-secure packet ++// This makes sure that those packets can always be retransmitted without splitting the contained StreamFrames ++const NonForwardSecurePacketSizeReduction = 50 ++ + // DefaultMaxCongestionWindow is the default for the max congestion window + const DefaultMaxCongestionWindow = 1000 + ","I would prefer to not have a magic number, but construct this value out of other constants we already have." +905,"@@ -101,6 +101,15 @@ def setup_authentication(config): + from configuration. + """""" + config.include('pyramid_multiauth') ++ settings = config.get_settings() ++ ++ policies = aslist(settings['multiauth.policies']) ++ if 'basicauth' in policies: ++ config.add_api_capability( ++ ""basicauth"", ++ description=""Very basic authentication sessions. Not for production use."", ++ url=""http://kinto.readthedocs.io/en/stable/api/1.x/authentication.html"", ++ ) + + # Track policy used, for prefixing user_id and for logging. + def on_policy_selected(event):","The limitation is if somebody configure another policy with the same name, but it is an edge case we can ignore I guess." +906,"@@ -31,8 +31,8 @@ import ( + _ ""gocloud.dev/secrets/awskms"" + _ ""gocloud.dev/secrets/azurekeyvault"" + _ ""gocloud.dev/secrets/gcpkms"" +- _ ""gocloud.dev/secrets/hashivault"" + _ ""gocloud.dev/secrets/localsecrets"" ++ _ ""gocloud.dev/secrets/vault"" + ) + + const helpSuffix = `",? The package is named `hashivault`. +907,"@@ -240,6 +240,9 @@ static int config_ini_handler(void *user, const char *section, const char *name, + if (strcmp(name, ""xwayland"") == 0) { + if (strcasecmp(value, ""true"") == 0) { + config->xwayland = true; ++ } else if (strcasecmp(value, ""lazy"") == 0) { ++ config->xwayland = true; ++ config->xwayland_lazy = true; + } else if (strcasecmp(value, ""false"") == 0) { + config->xwayland = false; + } else {","I don't think this should enable xwayland, because it's convenient to toggle xwayland just by setting `xwayland` to `false`" +908,"@@ -28,7 +28,6 @@ import ( + fakeclientset ""k8s.io/client-go/kubernetes/fake"" + certutil ""k8s.io/client-go/util/cert"" + ""k8s.io/client-go/util/keyutil"" +- + fakeaggregatorclientset ""k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"" + ) + ",Remove this line by accident? +909,"@@ -16,12 +16,13 @@ + + package com.palantir.baseline.plugins; + ++import java.util.Collections; + import java.util.Objects; + import org.gradle.api.Plugin; + import org.gradle.api.Project; + import org.gradle.api.artifacts.Dependency; +-import org.gradle.api.plugins.JavaPluginConvention; + import org.gradle.api.tasks.SourceSet; ++import org.gradle.api.tasks.SourceSetContainer; + import org.gradle.api.tasks.compile.JavaCompile; + + public final class BaselineImmutables implements Plugin {","Calling `.stream()` on a `DomainObjectCollection` is pretty much always a bug, as it doesn't include objects added later (and encourages people to use afterEvaluate). I wonder if we should make this an error prone check?" +910,"@@ -201,7 +201,10 @@ func CreateGitIgnore(targetDir string, ignores ...string) error { + + if fileutil.FileExists(gitIgnoreFilePath) { + sigFound, err := fileutil.FgrepStringInFile(gitIgnoreFilePath, DdevFileSignature) +- util.CheckErr(err) ++ if err != nil { ++ return err ++ } ++ + // If we sigFound the file and did not find the signature in .ddev/.gitignore, warn about it. + if !sigFound { + util.Warning(""User-managed %s will not be managed/overwritten by ddev"", gitIgnoreFilePath)","Thanks for paying attention to other places this might happen. This one is particularly important; I probably never should have gotten in the habit of CheckErr(), since it does a log.Panic() explicitly, which looks like something else until you look closely. It's supposed to be used places where ""can't happen"" but Things Can Happen." +911,"@@ -275,6 +275,15 @@ func (b *ofFlowBuilder) MatchARPOp(op uint16) FlowBuilder { + return b + } + ++// MatchIPDscp adds match condition for matching DSCP field in the IP header. Note, OVS use TOS to present DSCP, and ++// the field name is shown as ""nw_tos"" with OVS command line, and the value is calculated by shifting the given value ++// left 2 bits. ++func (b *ofFlowBuilder) MatchIPDscp(dscp uint8) FlowBuilder { ++ b.matchers = append(b.matchers, fmt.Sprintf(""nw_tos=%d"", dscp<<2)) ++ b.Match.IpDscp = dscp ++ return b ++} ++ + // MatchConjID adds match condition for matching conj_id. + func (b *ofFlowBuilder) MatchConjID(value uint32) FlowBuilder { + b.matchers = append(b.matchers, fmt.Sprintf(""conj_id=%d"", value))",What is the different between nw_tos and ip_dscp? Only high 6 bits vs low 6 bits and supported version? +912,"@@ -329,12 +329,17 @@ extern ""C"" bool isValidMolBlob(char *data, int len) { + return res; + } + +-extern ""C"" char *makeMolText(CROMol data, int *len, bool asSmarts) { ++extern ""C"" char *makeMolText(CROMol data, int *len, bool asSmarts, ++ bool cxSmiles) { + ROMol *mol = (ROMol *)data; + + try { + if (!asSmarts) { +- StringData = MolToSmiles(*mol, true); ++ if (!cxSmiles) { ++ StringData = MolToSmiles(*mol); ++ } else { ++ StringData = MolToCXSmiles(*mol); ++ } + } else { + StringData = MolToSmarts(*mol, false); + }",I'm assuming that asSmarts & cxSmiles == asSmarts +913,"@@ -780,7 +780,9 @@ class LabelledData(param.Parameterized): + except: + self.warning(""Could not unpickle custom style information."") + self.__dict__.update(d) +- ++ # TODO: super's setstate not called? ++ if ""param"" not in self.__dict__: ++ self.param = type(self.param)(self.__class__, self=self) + + + class Dimensioned(LabelledData):",Seems like an oversight but I don't think the super would do anything else in this case unless I'm mistaken. +914,"@@ -30,8 +30,8 @@ namespace Examples.Console + internal class InstrumentationWithActivitySource : IDisposable + { + private const string RequestPath = ""/api/request""; +- private SampleServer server = new SampleServer(); +- private SampleClient client = new SampleClient(); ++ private readonly SampleServer server = new SampleServer(); ++ private readonly SampleClient client = new SampleClient(); + + public void Start(ushort port = 19999) + {","Curious, do we consider this as pedantic for example code?" +915,"@@ -609,7 +609,7 @@ class AdminController extends Controller + + $formType = $this->useLegacyFormComponent() ? 'easyadmin' : 'JavierEguiluz\\Bundle\\EasyAdminBundle\\Form\\Type\\EasyAdminFormType'; + +- return $this->get('form.factory')->createNamedBuilder('form', $formType, $entity, $formOptions); ++ return $this->get('form.factory')->createNamedBuilder(strtolower($this->entity['name']), $formType, $entity, $formOptions); + } + + /**","Should we convert the entity name to snake case using `Doctrine\Common\Inflector\Inflector::tableize` or similar ? Should a `snaked_name` or whatever be part of the entity metadata in order to use it for form names, ids, & other html attributes ?" +916,"@@ -12,9 +12,15 @@ func NewClientFake(IP string) Client { + + type clientFake struct { + ip string ++ outboundIp string + } + +-func (client *clientFake) GetIp() (string, error) { ++func (client *clientFake) GetPublicIP() (string, error) { ++ log.Info(IPIFY_API_LOG_PREFIX, ""IP faked: "", client.ip) ++ return client.ip, nil ++} ++ ++func (client *clientFake) GetOutboundIP() (string, error) { + log.Info(IPIFY_API_LOG_PREFIX, ""IP faked: "", client.ip) + return client.ip, nil + }",Should be `client.outboundIp` +917,"@@ -31,6 +31,9 @@ + // THE POSSIBILITY OF SUCH DAMAGE. + // + ++using System.IO; ++using System.Threading.Tasks; ++ + namespace NLog.UnitTests.LayoutRenderers + { + using System;",Must these `using` statements not go inside the `namespace` block? +918,"@@ -92,8 +92,8 @@ type fboMutexLevel mutexLevel + + const ( + fboMDWriter fboMutexLevel = 1 +- fboHead = 2 +- fboBlock = 3 ++ fboHead fboMutexLevel = 2 ++ fboBlock fboMutexLevel = 3 + ) + + func (o fboMutexLevel) String() string {",Why? I thought the previous way was idiomatic. (Same with the `MetadataVer` stuff above.) +919,"@@ -12,11 +12,7 @@ define([], function() { + } + + function uploadContent(connectionManager, server, options) { +- return new Promise(function(resolve, reject) { +- require([""contentuploader""], function(ContentUploader) { +- (new ContentUploader).uploadImages(connectionManager, server).then(resolve, reject) +- }) +- }) ++ return new Promise().resolve(); + } + + function syncMedia(connectionManager, server, options) {",shouldn't we `reject` here instead? +920,"@@ -167,10 +167,12 @@ func printActionProto(action *iotextypes.Action) (string, error) { + if err != nil { + return """", output.NewError(output.ConvertError, ""failed to convert bytes into address"", err) + } ++ //ioctl action should display IOTX unit instead Raul ++ gasPriceUnitIOTX, err := util.StringToIOTX(action.Core.GasPrice) + result := fmt.Sprintf(""\nversion: %d "", action.Core.GetVersion()) + + fmt.Sprintf(""nonce: %d "", action.Core.GetNonce()) + + fmt.Sprintf(""gasLimit: %d "", action.Core.GasLimit) + +- fmt.Sprintf(""gasPrice: %s Rau\n"", action.Core.GasPrice) + ++ fmt.Sprintf(""gasPrice: %s IOTX\n"", gasPriceUnitIOTX) + + fmt.Sprintf(""senderAddress: %s %s\n"", senderAddress.String(), + Match(senderAddress.String(), ""address"")) + switch {","check err or use gasPriceUnitIOTX, _ := if we are sure action.Core.GasPrice is correct" +921,"@@ -34,7 +34,7 @@ func newHarness(t *testing.T) (drivertest.Harness, error) { + return &harness{vars: map[string][]byte{}}, nil + } + +-func (h *harness) MakeWatcher(ctx context.Context, name string, decoder *runtimevar.Decoder, wait time.Duration) (driver.Watcher, error) { ++func (h *harness) MakeWatcher(ctx context.Context, name string, decoder *runtimevar.Decoder) (driver.Watcher, error) { + rawVal, found := h.vars[name] + if !found { + // The variable isn't set. Create a Variable that always returns an error.","Just curious, was wait not used at all before?" +922,"@@ -7,9 +7,10 @@ package manifest + import ( + ""errors"" + ""fmt"" ++ ""github.com/google/shlex"" + ""path/filepath"" + ""strconv"" +- ""strings"" ++ //""strings"" + + ""github.com/aws/aws-sdk-go/aws"" + ""gopkg.in/yaml.v3""",nit: can we remove this? +923,"@@ -44,11 +44,11 @@ public class NotificationStore { + } + } + +- public Notification get(int index) { ++ public synchronized Notification get(int index) { + return store.get(index); + } + +- public void add(Notification n) { ++ public synchronized void add(Notification n) { + log.info(""Notification received: "" + n.text); + for (int i = 0; i < store.size(); i++) { + if (get(i).id == n.id) {",is it not a problem when one synchronized function is called by other? +924,"@@ -1,6 +1,7 @@ + ActiveAdmin.register Account do +- permit_params :level +- actions :index, :show, :edit ++ permit_params :login, :email, :level, :country_code, :location, :url, :hide_experience, :email_master, :email_posts, ++ :email_kudos, :email_new_followers, :twitter_account, :affiliation_type, :organization_name ++ actions :index, :show, :edit, :update + + controller do + defaults finder: :fetch_by_login_or_email","We (even as admins) shouldn't override the User Preference settings like `email_master`, `email_posts`, `email_kudos`, `email_new_followers`. These all would be set by the user of their choice. Please do remove these attributes from editing//updating. Thanks!" +925,"@@ -20,7 +20,7 @@ return [ + 'alpha_dash' => 'O campo :attribute deve conter apenas letras, números e traços.', + 'alpha_num' => 'O campo :attribute deve conter apenas letras e números .', + 'array' => 'O campo :attribute deve conter um array.', +- 'attached' => 'This :attribute is already attached.', ++ 'attached' => 'Este :attribute já está ligado.', + 'before' => 'O campo :attribute deve conter uma data anterior a :date.', + 'before_or_equal' => 'O campo :attribute deve conter uma data inferior ou igual a :date.', + 'between' => [","""Este :attribute j est anexado."" sounds better." +926,"@@ -0,0 +1,6 @@ ++ ++if __name__ == ""__main__"": ++ import doctest ++ import databricks.koalas as ks ++ from databricks.koalas import frame, series ++ doctest.testmod(frame, extraglobs={""ks"": ks})","This line should be repeated for every module that needs testing. One cannot rely on nosetest to automatically discover all the modules. On the bright side, there is no need to change any of the other files." +927,"@@ -301,5 +301,3 @@ var failedIssuanceMu sync.RWMutex + // If this value is recent, do not make any on-demand certificate requests. + var lastIssueTime time.Time + var lastIssueTimeMu sync.Mutex +- +-var errNoCert = errors.New(""no certificate available"")",This error was unused +928,"@@ -212,6 +212,11 @@ type ( + PreviousRangeID int64 + } + ++ // CloseShardRequest is used to notify persistence that we're unloading a shard ++ CloseShardRequest struct { ++ ShardID int32 ++ } ++ + // AddTasksRequest is used to write new tasks + AddTasksRequest struct { + ShardID int32","Personally I wish we didn't have a proto for every single little thing we do. RequestShardAction with an enum for the action type would be a lot cleaner imo, but I'm pretty sure that ship has sailed :) Just kvetching." +929,"@@ -0,0 +1,5 @@ ++<% if trail.complete? %> ++ <%= render ""completed_trails/trail"", trail: trail %> ++<% else %> ++ <%= render ""trails/incomplete_trail"", trail: trail %> ++<% end %>",Does this make more sense as `trails/_trail` now? +930,"@@ -435,6 +435,17 @@ func (agent *ecsAgent) getEC2InstanceID() string { + return instanceID + } + ++// getoutpostARN gets the Outpost ARN from the metadata service ++func (agent *ecsAgent) getoutpostARN() string { ++ outpostARN, err := agent.ec2MetadataClient.OutpostARN() ++ if err != nil { ++ seelog.Warnf( ++ ""Unable to obtain Outpost ARN from EC2 Metadata: %v"", err) ++ return """" ++ } ++ return outpostARN ++} ++ + // newStateManager creates a new state manager object for the task engine. + // Rest of the parameters are pointers and it's expected that all of these + // will be backfilled when state manager's Load() method is invoked","synced offline. let's move this to `agent_unix.go` to make the IMDS call, since this is not supported in Windows." +931,"@@ -12,6 +12,10 @@ class PythonMappings + fun.add_mapping(""py_env"", Python::VirtualEnv.new) + + fun.add_mapping(""py_docs"", Python::GenerateDocs.new) ++ ++ fun.add_mapping(""py_install"", Python::Install.new) ++ ++ fun.add_mapping(""py_prep"", Python::Prep.new) + end + end + ","Too much indentation here. Should match the lines above, which have four spaces." +932,"@@ -15,14 +15,6 @@ BOOST_AUTO_TEST_CASE(test_incompatible_with_mld) + osrm::exception); + } + +-BOOST_AUTO_TEST_CASE(test_incompatible_with_corech) +-{ +- // Note - CH-only data can't be used with the CoreCH algorithm +- BOOST_CHECK_THROW( +- getOSRM(OSRM_TEST_DATA_DIR ""/ch/monaco.osrm"", osrm::EngineConfig::Algorithm::CoreCH), +- osrm::exception); +-} +- + BOOST_AUTO_TEST_CASE(test_incompatible_with_ch) + { + // Can't use the CH algorithm with MLD data",Same here we still need this test to make sure the fallback works. +933,"@@ -0,0 +1,8 @@ ++using System; ++namespace MvvmCross.iOS.Views.Presenters.Attributes ++{ ++ public interface IMvxOverridePresentationAttribute ++ { ++ MvxBasePresentationAttribute OverridePresentationAttribute(); ++ } ++}",I'm wondering if we can actually base this on a `IMvxPresentationAttribute` instead of the base one. +934,"@@ -430,7 +430,7 @@ export function unmount(vnode, parentVNode, skipRemove) { + } + } + +- r.base = r._parentDom = null; ++ r.base = r._parentDom = r._vnode = vnode._component = null; + } + + if ((r = vnode._children)) {",could we switch to `undefined` here? +935,"@@ -94,6 +94,7 @@ public class SyncManager { + this.smartStore = smartStore; + this.restClient = restClient; + SyncState.setupSyncsSoupIfNeeded(smartStore); ++ SyncState.cleanupSyncsSoupIfNeeded(smartStore); + } + + /**",The cleanup call +936,"@@ -288,10 +288,11 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', + icon: 'album' + }); + } +- +- if (options.openArtist !== false && item.ArtistItems && item.ArtistItems.length) { ++ // Show Album Artist by default, as a song can have multiple artists, which specific one would this option refer to? ++ // Although some albums can have multiple artists, it's not as common as songs. ++ if (options.openArtist !== false && item.AlbumArtists && item.AlbumArtists.length) { + commands.push({ +- name: globalize.translate('ViewArtist'), ++ name: globalize.translate('ViewAlbumArtist'), + id: 'artist', + icon: 'person' + });","I think ""View artist"" is a bit more standard and expected. Or even ""Go to artist"" to take the Spotify terminology as-is." +937,"@@ -196,6 +196,9 @@ module Bolt + # This works on deeply nested data structures composed of Hashes, Arrays, and + # and plain-old data types (int, string, etc). + def unwrap_sensitive_args(arguments) ++ # Skip this if Puppet isn't loaded ++ return arguments unless defined?(Puppet::Pops::Types::PSensitiveType::Sensitive) ++ + case arguments + when Array + # iterate over the array, unwrapping all elements",It might make sense to refactor this later so that we use a Bolt-native type to hide sensitive values. +938,"@@ -30,3 +30,7 @@ from extensive_tm_test_base import ExtensiveTemporalMemoryTest + class ExtensiveTemporalMemoryTestCPP(ExtensiveTemporalMemoryTest, unittest.TestCase): + def getTMClass(self): + return nupic.bindings.algorithms.TemporalMemory ++ ++ ++if __name__ == ""__main__"": ++ unittest.main()",We were trying to move away from this to force people to always run tests under py.test. +939,"@@ -933,6 +933,8 @@ from selenium.webdriver.common.keys import Keys + + browser = self._check_platform() + ++ body.append(self._get_selenium_options()) ++ + if browser == 'firefox': + body.extend(self._get_firefox_options() + self._get_firefox_profile() + [self._get_firefox_webdriver()]) + ",1 - create browser specific options class: - chromeoptions - firefoxoptions - argsoptions +940,"@@ -681,7 +681,9 @@ class ProxyListenerS3(ProxyListener): + + # fix content-type: https://github.com/localstack/localstack/issues/618 + # https://github.com/localstack/localstack/issues/549 +- if 'text/html' in response.headers.get('Content-Type', ''): ++ # https://github.com/localstack/localstack/issues/854 ++ if 'text/html' in response.headers.get('Content-Type', '') \ ++ and not response_content_str.startswith(' 'Backend\Skins\Standard', + ++ /* ++ |-------------------------------------------------------------------------- ++ | Determines if logging in backend should run UpdateManager ++ |-------------------------------------------------------------------------- ++ | ++ | If value is true it runs UpdateMananger after login in backend. ++ | It's recommended to set this value to 'false' in production enviroments ++ | because it cleares cache on every login in backend. ++ | ++ */ ++ ++ 'runUpdateManagerAfterBackendLogin' => true, ++ + /* + |-------------------------------------------------------------------------- + | Determines which modules to load","@Samuell1 Might be better to say ""Automatically check for plugin updates on login""." +947,"@@ -1,4 +1,6 @@ ++using System; + using System.Diagnostics; ++using System.Runtime.CompilerServices; + + namespace Datadog.Trace.Util + {",Thanks for the additional Process helper! Can we also cache the first `Process.GetCurrentProcess()` result in a static field so we don't have to repeatedly call it? It means we would also need to dispose it when the static `_runtimeMetricsWriter` instance is disposed +948,"@@ -73,6 +73,19 @@ func (*mockStatsEngine) GetTaskHealthMetrics() (*ecstcs.HealthMetadata, []*ecstc + return nil, nil, nil + } + ++// TestDisableMetrics tests the StartMetricsSession will return immediately if ++// the metrics was disabled ++func TestDisableMetrics(t *testing.T) { ++ params := TelemetrySessionParams{ ++ Cfg: &config.Config{ ++ DisableMetrics: true, ++ DisableDockerHealthCheck: true, ++ }, ++ } ++ ++ StartMetricsSession(params) ++} ++ + func TestFormatURL(t *testing.T) { + endpoint := ""http://127.0.0.0.1/"" + wsurl := formatURL(endpoint, testClusterArn, testInstanceArn)","just wondering what is the result of breaking the logic we test here? it seems that in that case we will just not return immediately, but i'm not sure whether the test will fail?" +949,"@@ -198,8 +198,9 @@ func TestInferModulePath(t *testing.T) { + t.Error(err) + } + }() +- +- pctx := newTestProcessContext(dir) ++ srcDir := filepath.Join(dir, ""src"") ++ os.Mkdir(srcDir, 0777) ++ pctx := newTestProcessContext(srcDir) + gopath, cleanup := tc.testGOPATH(dir) + defer cleanup() + pctx.env = []string{gopath}",We should fail the test if this returns `err != nil`. +950,"@@ -140,6 +140,9 @@ func (r *ReconcileClusterDeployment) reconcileExistingInstallingClusterInstall(c + } + + updated = false ++ // Fun extra variable to keep track of whether we should increment metricProvisionFailedTerminal ++ // later; because we only want to do that if (we change that status and) the status update succeeds. ++ provisionFailedTerminal := false + conditions, updated = controllerutils.SetClusterDeploymentConditionWithChangeCheck(conditions, + hivev1.ProvisionStoppedCondition, + stopped.Status,",What is the drawback of not having this flag as a gating condition to report the metric? +951,"@@ -22,9 +22,14 @@ import ( + ) + + func gracefullyStopProcess(pid int) error { ++ fmt.Printf(""Graceful stop..."") + err := syscall.Kill(pid, syscall.SIGINT) + if err != nil { + return fmt.Errorf(""kill: %v"", err) + } + return nil + } ++ ++func getAppName() string { ++ return filepath.Base(os.Args[0]) ++}","`getProcessName()` will be less ambiguous, since Caddy has ""apps"" that it runs internally." +952,"@@ -4741,6 +4741,7 @@ const char * const DMLFormats[] = + ""%s"", // DML_IL + ""%s"", // DML_ComWrapperRCW + ""%s"", // DML_ComWrapperCCW ++ ""%s"", // DML_TaggedMemory (hardcoded current size to 2 pointer sizes) + }; + + void ConvertToLower(__out_ecount(len) char *buffer, size_t len)","Is there any way to not hardcode this given we know the size in bytes? The public API has the flexibility of being a Span. Should we maybe not do anything printing DML? The runtime allocates the buffer, but it's a ""scratch memory"" area, The delegate gets it passed in and they decide how to use it. Also, how is DML used if the feature is for macOS support?" +953,"@@ -64,6 +64,13 @@ nebula::cpp2::ErrorCode ScanEdgeProcessor::checkAndBuildContexts(const cpp2::Sca + std::vector returnProps = {*req.return_columns_ref()}; + ret = handleEdgeProps(returnProps); + buildEdgeColName(returnProps); ++ ret = buildFilter(req, [](const cpp2::ScanEdgeRequest& r) -> const std::string* { ++ if (r.filter_ref().has_value()) { ++ return r.get_filter(); ++ } else { ++ return nullptr; ++ } ++ }); + return ret; + } + ",How about just override the `buildFilter`? Passing another function here is a little weird. +954,"@@ -71,8 +71,9 @@ var ( + + ignoredPackages = app.Flag(""ignored-packages"", ""Space separated list of specs ignoring rebuilds if their dependencies have been updated. Will still build if all of the spec's RPMs have not been built."").String() + +- pkgsToBuild = app.Flag(""packages"", ""Space separated list of top-level packages that should be built. Omit this argument to build all packages."").String() +- pkgsToRebuild = app.Flag(""rebuild-packages"", ""Space separated list of base package names packages that should be rebuilt."").String() ++ pkgsToBuild = app.Flag(""packages"", ""Space separated list of top-level packages that should be built. Omit this argument to build all packages."").String() ++ pkgsToRebuild = app.Flag(""rebuild-packages"", ""Space separated list of base package names packages that should be rebuilt."").String() ++ rpmHydratedTest = app.Flag(""rpm-hydrated-test"", ""Is this just a TestRPM build with all RPMs hydrated?"").String() + + logFile = exe.LogFileFlag(app) + logLevel = exe.LogLevelFlag(app)","This should just be a `.Bool()` flag I think, we don't encode anything beyond y/n here. See `$(RUN_CHECK)` and `$(STOP_ON_PKG_FAIL)` for examples of how to pass those in." +955,"@@ -2042,6 +2042,7 @@ bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Promise( + address.SetLoadAddress(val_ptr_addr, &m_process->GetTarget()); + return true; + } break; ++ case swift::MetadataKind::Function: + case swift::MetadataKind::Optional: + case swift::MetadataKind::Struct: + case swift::MetadataKind::Tuple: {",Is this needed? +956,"@@ -348,7 +348,7 @@ export default Ember.Controller.extend(BillingCategories, EKMixin, + confirmDeleteValue(value) { + let i18n = this.get('i18n'); + let title = i18n.t('admin.lookup.titles.deleteLookupValue'); +- let message = i18n.t('admin.lookup.messages.deleteLookupValue', { value }); ++ let message = i18n.t('messages.delete_singular', { name: value.concat(' value') }); + this.displayConfirm(title, message, 'deleteValue', Ember.Object.create({ + valueToDelete: value + }));",This code is passing a non localized string when it should be passing in a localized string or it should use the name of the item being deleted. +957,"@@ -18,6 +18,8 @@ package container + import ( + ""context"" + ++ ""github.com/chaos-mesh/chaos-mesh/pkg/selector/generic"" ++ + ""go.uber.org/fx"" + v1 ""k8s.io/api/core/v1"" + ""sigs.k8s.io/controller-runtime/pkg/client""",how about moving it under L26 +958,"@@ -0,0 +1,17 @@ ++/** ++ * Memoize a function. ++ * @method memoize ++ * @memberof axe.utils ++ * @param {Function} fn Function to memoize ++ * @return {Function} ++ */ ++axe._memoizedFns = []; ++axe.utils.memoize = function(fn) { ++ // keep track of each function that is memoized so it can be cleared at ++ // the end of a run. each memoized function has its own cache, so there is ++ // no method to clear all memoized caches. instead, we have to clear each ++ // individual memoized function ourselves. ++ const memoized = axe.imports.memoize(fn); ++ axe._memoizedFns.push(memoized); ++ return memoized; ++};",I think this needs to be tested +959,"@@ -2,6 +2,9 @@ class Trail < ApplicationRecord + extend FriendlyId + + include PgSearch ++ ++ DEFAULT_IMAGE_URL = ""https://images.thoughtbot.com/upcase/trail-title-cards/default.jpg"" ++ + multisearchable against: [:name, :description], if: :published? + + validates :name, :description, presence: true",Style/MutableConstant: Freeze mutable objects assigned to constants. +960,"@@ -155,16 +155,15 @@ public final class DeflateWithPresetDictCompressionMode extends CompressionMode + + private static class DeflateWithPresetDictCompressor extends Compressor { + +- final byte[] dictBytes; +- final int blockLength; ++ private final int dictLength, blockLength; + final Deflater compressor; + byte[] compressed; + boolean closed; + + DeflateWithPresetDictCompressor(int level, int dictLength, int blockLength) { +- compressor = new Deflater(level, true); ++ compressor = BugfixDeflater_JDK8252739.createDeflaterInstance(level, true, dictLength); + compressed = new byte[64]; +- this.dictBytes = new byte[dictLength]; ++ this.dictLength = dictLength; + this.blockLength = blockLength; + } + ","Just a thought, really. If it's a bug that can be probed for (and it can be - see Adrian's repro) then it could as well be a static initialization of a supplier of Deflater instances; if we probe for a buggy JVM, we return the wrapper. If we don't we return the Deflater. This way on non-affected JVMs nothing happens and if we do use the wrapper, we know the JVM is broken." +961,"@@ -95,7 +95,7 @@ public class FSTTester { + return br; + } + +- static String getRandomString(Random random) { ++ public static String getRandomString(Random random) { + final String term; + if (random.nextBoolean()) { + term = TestUtil.randomRealisticUnicodeString(random);",Looks like this should be publicly accessible for tests in any modules? +962,"@@ -19,7 +19,7 @@ if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) { + throw new RuntimeException('Please run ""composer require symfony/dotenv"" to load the "".env"" files configuring the application.'); + } else { + $path = dirname(__DIR__).'/.env'; +- $dotenv = new Dotenv(false); ++ $dotenv = new Dotenv(true); + + // load all the .env files + if (method_exists($dotenv, 'loadEnv')) {",Allow putenv is necessary to be able to get environment variables with `getenv`? +963,"@@ -0,0 +1,17 @@ ++#include ++#include ++using namespace std; ++ ++int main() ++{ ++ int year; ++ cout<<""Enter year to check\n""; ++ cin>>year; ++ if((year%4==0 && year%100!=0) || year%400==0){ ++ cout<<""leap year.\n""; ++ } ++ else{ ++ cout<<"" Not leap year.\n""; ++ } ++ return 0; ++}",use function to check it. - don't do everything in main +964,"@@ -50,7 +50,7 @@ class BaseRulesEngine(object): + self.full_rules_path = rules_file_path.strip() + self.snapshot_timestamp = snapshot_timestamp + +- def build_rule_book(self): ++ def build_rule_book(self, global_configs): + """"""Build RuleBook from the rules definition file."""""" + raise NotImplementedError('Implement in a child class.') + ",Sorry I'm confused. Why not kwarg this like the others? +965,"@@ -7171,15 +7171,15 @@ const instr_info_t vex_W_extensions[][2] = { + * registers are identical. We don't bother trying to detect that. + */ + {OP_vpgatherdd,0x66389018,""vpgatherdd"",Vx,Hx,MVd,Hx,xx, mrm|vex|reqp,x,END_LIST}, +- {OP_vpgatherdq,0x66389058,""vpgatherdq"",Vx,Hx,MVq,Hx,xx, mrm|vex|reqp,x,END_LIST}, ++ {OP_vpgatherdq,0x66389058,""vpgatherdq"",Vx,Hx,MVd,Hx,xx, mrm|vex|reqp,x,END_LIST}, + }, { /* vex_W_ext 67 */ +- {OP_vpgatherqd,0x66389118,""vpgatherqd"",Vx,Hx,MVd,Hx,xx, mrm|vex|reqp,x,END_LIST}, ++ {OP_vpgatherqd,0x66389118,""vpgatherqd"",Vx,Hx,MVq,Hx,xx, mrm|vex|reqp,x,END_LIST}, + {OP_vpgatherqq,0x66389158,""vpgatherqq"",Vx,Hx,MVq,Hx,xx, mrm|vex|reqp,x,END_LIST}, + }, { /* vex_W_ext 68 */ + {OP_vgatherdps,0x66389218,""vgatherdps"",Vvs,Hx,MVd,Hx,xx, mrm|vex|reqp,x,END_LIST}, +- {OP_vgatherdpd,0x66389258,""vgatherdpd"",Vvd,Hx,MVq,Hx,xx, mrm|vex|reqp,x,END_LIST}, ++ {OP_vgatherdpd,0x66389258,""vgatherdpd"",Vvd,Hx,MVd,Hx,xx, mrm|vex|reqp,x,END_LIST}, + }, { /* vex_W_ext 69 */ +- {OP_vgatherqps,0x66389318,""vgatherqps"",Vvs,Hx,MVd,Hx,xx, mrm|vex|reqp,x,END_LIST}, ++ {OP_vgatherqps,0x66389318,""vgatherqps"",Vvs,Hx,MVq,Hx,xx, mrm|vex|reqp,x,END_LIST}, + {OP_vgatherqpd,0x66389358,""vgatherqpd"",Vvd,Hx,MVq,Hx,xx, mrm|vex|reqp,x,END_LIST}, + }, { /* vex_W_ext 70 */ + {OP_vpmaskmovd,0x66388c18,""vpmaskmovd"",Vx,xx,Hx,Mx,xx, mrm|vex|reqp|predcx,x,tvexw[71][0]},","First, any changes here should be synchronized with instr_compute_VSIB_index(). Second, the original looks correct to me: the first letter of the opcode name suffix is the index size, while the second is the memory size. So ""vpgatherdq"" is a d-sized index and q-sized memory. The operand size we store for memory accesses is always the memory size, not the address size, and for VSIB we store a single memory element size. It looks like we have no inside-opnd_t storage of the index size: that's done by dispatch on opcode it seems. I have a bunch of notes of discussions on how to handle VSIB: we decided to bail on encoding too much inside the opnd_t I guess." +966,"@@ -118,6 +118,9 @@ class ExternalProgramTask(luigi.Task): + file_object.seek(0) + return ''.join(map(lambda s: s.decode('utf-8'), file_object.readlines())) + ++ def build_tracking_url(self, logs_output): ++ return logs_output ++ + def run(self): + args = list(map(str, self.program_args())) + ",Sorry for going back and forth. Adding docstring here would be very helpful for others to understand the need of this method. +967,"@@ -121,10 +121,7 @@ bool Creature::canSee(const Position& pos) const + + bool Creature::canSeeCreature(const Creature* creature) const + { +- if (!canSeeInvisibility() && creature->isInvisible()) { +- return false; +- } +- return true; ++ return canSeeInvisibility() && creature->isInvisible(); + } + + void Creature::setSkull(Skulls_t newSkull)",You introduced a bug here. +968,"@@ -261,6 +261,14 @@ namespace Microsoft.DotNet.Build.Tasks.VersionTools + ""true"", + StringComparison.OrdinalIgnoreCase); + ++ string oldValue = step.GetMetadata(""ReplacementSubstituteOld""); ++ string newValue = step.GetMetadata(""ReplacementSubstituteNew""); ++ ++ if (!string.IsNullOrEmpty(oldValue) && !string.IsNullOrEmpty(newValue)) ++ { ++ updater.ReplacementTransform = v => v.Replace(oldValue, newValue); ++ } ++ + return updater; + } + ",Should we log a warning/error if only one is specified and not the other? +969,"@@ -463,4 +463,15 @@ func (c *fakeClient) ReportApplicationLiveStateEvents(ctx context.Context, req * + return &pipedservice.ReportApplicationLiveStateEventsResponse{}, nil + } + ++func (c *fakeClient) GetLatestEvent(ctx context.Context, req *pipedservice.GetLatestEventRequest, opts ...grpc.CallOption) (*pipedservice.GetLatestEventResponse, error) { ++ c.logger.Info(""fake client received GetLatestEvent rpc"", zap.Any(""request"", req)) ++ return &pipedservice.GetLatestEventResponse{ ++ Event: &model.Event{ ++ Id: ""dev"", ++ Name: ""dev"", ++ ProjectId: ""dev"", ++ }, ++ }, nil ++} ++ + var _ pipedservice.PipedServiceClient = (*fakeClient)(nil)",`ctx` is unused in GetLatestEvent +970,"@@ -128,6 +128,14 @@ void nano_daemon::daemon::run (boost::filesystem::path const & data_path, nano:: + logger.always_log (boost::format (""Open file descriptors limit is %1%"") % file_descriptor_limit); + } + ++ // a 0-valued port means for the node 'let the OS decide'; however, for the daemon start up, if ++ // the user hasn't specified a port in the config, we must use the default peering port for the network ++ // ++ if (!config.node.peering_port) ++ { ++ config.node.peering_port = network_params.network.default_node_port; ++ } ++ + auto node (std::make_shared (io_ctx, data_path, config.node, opencl_work, flags)); + if (!node->init_error ()) + {","This looks good to me. Personally, I would have the following for maximum flexibility: * convert peering_port from uint64_t to int. * Set the default value to ""-1"" to specify the value is not set * if the value is -1 then do `config.node.peering_port = network_params.network.default_node_port` That would allow for 0 to mean, select the port number yourself and be more consistent. But I am happy with the change as is, as well." +971,"@@ -10,7 +10,6 @@ __all__ = [ + + class ImageTransform(object): + """"""Preprocess an image. +- + 1. rescale the image to expected size + 2. normalize the image + 3. flip the image (if needed)",The blank line between the summary and detailed description is better to be kept. +972,"@@ -167,6 +167,11 @@ func (a *API) Setup() { + a.setMetadataEndpointsKey() + a.writeShapeNames() + a.resolveReferences() ++ ++ if !a.NoRemoveUnusedShapes { ++ a.removeUnusedShapes() ++ } ++ + a.fixStutterNames() + a.renameExportable() + a.applyShapeNameAliases()","Curiously, are these indents intended or should they be aligned?" +973,"@@ -1130,7 +1130,9 @@ def getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD + else: + tableID = None + +- roleText=getSpeechTextForProperties(reason=reason,role=role) ++ roleText=attrs.get('roleText') ++ if not roleText: ++ roleText=getSpeechTextForProperties(reason=reason,role=role) + stateText=getSpeechTextForProperties(reason=reason,states=states,_role=role) + keyboardShortcutText=getSpeechTextForProperties(reason=reason,keyboardShortcut=keyboardShortcut) if config.conf[""presentation""][""reportKeyboardShortcuts""] else """" + ariaCurrentText=getSpeechTextForProperties(reason=reason,current=ariaCurrent)","What if we changed this to this? roleText=attrs.get('roleText', lambda:getSpeechTextForProperties(reason=reason,role=role)) That will prevent the function from ever needing called in the roletext case, and removes that if." +974,"@@ -4801,7 +4801,15 @@ master_signal_handler_C(byte *xsp) + return; + } + #endif +- dcontext_t *dcontext = get_thread_private_dcontext(); ++ /* We avoid using safe_read_tls_magic during detach. This thread may already have ++ * lost its TLS. A safe read may result into a race affecting asynchronous non-alarm ++ * signals (xref i#3535) between delivering the SIGSEGV and restoring the app's signal ++ * handlers. We don't need the thread's private dcontext anymore here at this point. ++ * Note that there is still a small race window if the signal gets delivered after the ++ * detach has finished, i.e. doing_detach is false. This is an issue in particular if ++ * the app has started re-attaching. ++ */ ++ dcontext_t *dcontext = doing_detach ? NULL : get_thread_private_dcontext(); + + #ifdef MACOS + # ifdef X64",This will still result in a safe_read_tls_magic on AMD in tls_thread_preinit(). +975,"@@ -561,5 +561,4 @@ public class TestJdbcCatalog { + String nsString = JdbcUtil.namespaceToString(ns); + Assert.assertEquals(ns, JdbcUtil.stringToNamespace(nsString)); + } +- + }",Can you remove this change? +976,"@@ -48,7 +48,7 @@ func ValidateCertificateForACMEIssuer(crt *cmapi.CertificateSpec, issuer *cmapi. + el := field.ErrorList{} + + if crt.IsCA { +- el = append(el, field.Invalid(specPath.Child(""isCA""), crt.KeyAlgorithm, ""ACME does not support CA certificates"")) ++ el = append(el, field.Invalid(specPath.Child(""isCA""), crt.IsCA, ""ACME does not support CA certificates"")) + } + + if crt.Subject != nil && len(crt.Subject.Organizations) != 0 {","Oh, was that a bug in the validation?" +977,"@@ -134,6 +134,10 @@ public class OnlineFeedViewActivity extends AppCompatActivity { + } else { + Log.d(TAG, ""Activity was started with url "" + feedUrl); + setLoadingLayout(); ++ //Remove subscribeonandroid.com from feed URL in order to subscribe to the actual feed URL ++ if(feedUrl.contains(""subscribeonandroid.com"")){ ++ feedUrl = feedUrl.replaceFirst(""((www.)?(subscribeonandroid.com/))"",""""); ++ } + if (savedInstanceState == null) { + startFeedDownload(feedUrl, null, null); + } else {","Please use the Google java code style. Basically, add more space characters like in the statements below. Next to method arguments and curly braces. This is currently not checked on CI because it is too inconsistent in the code base but I would prefer new code to be consistent." +978,"@@ -145,10 +145,12 @@ TEST(UpdateEdgeTest, Set_Filter_Yield_Test) { + decltype(req.return_columns) tmpColumns; + tmpColumns.emplace_back(Expression::encode(val1)); + tmpColumns.emplace_back(Expression::encode(val2)); +- std::string name = folly::to(3002); +- std::string prop = ""tag_3002_col_2""; +- auto* sourcePropExp = new SourcePropertyExpression(&name, &prop); ++ delete val1; ++ delete val2; ++ auto* sourcePropExp = new SourcePropertyExpression( ++ new std::string(folly::to(3002)), new std::string(""tag_3002_col_2"")); + tmpColumns.emplace_back(Expression::encode(sourcePropExp)); ++ delete sourcePropExp; + + req.set_return_columns(std::move(tmpColumns)); + req.set_insertable(false);","Actually, I don't think we need to create object on heap." +979,"@@ -84,7 +84,7 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe + } + printer->Print(""import (\n""); + printer->Indent(); +- printer->Print(vars, ""$context$ \""golang.org/x/net/context\""\n""); ++ printer->Print(vars, ""$context$ \""context\""\n""); + printer->Print(vars, ""$grpc$ \""google.golang.org/grpc\""\n""); + printer->Outdent(); + printer->Print("")\n\n"");","this is a file we copy from gRPC, sp ideally it be fixed upstream as well.." +980,"@@ -14,7 +14,6 @@ + package zipkin2.storage.cassandra.v1; + + import com.datastax.driver.core.Session; +-import com.google.common.cache.CacheBuilderSpec; + import java.nio.ByteBuffer; + import java.util.ArrayList; + import java.util.LinkedHashSet;","changes like this, just strangle guava usages to be replaced by DelayLimiter into one place" +981,"@@ -27,8 +27,8 @@ const Widget = ( { + className, + slug, + noPadding, +- header: Header, +- footer: Footer, ++ Header, ++ Footer, + } ) => { + return ( + { ++public class BftForksSchedule { + + private final NavigableSet> forks = + new TreeSet<>(",Rename to ForksSchedule? Maybe in separate PR. +985,"@@ -1,11 +1,12 @@ +-import pytest + import time + from unittest import mock + ++import pytest ++ + from pyramid import testing + +-from kinto.core.storage import exceptions + from kinto.core.cache import heartbeat ++from kinto.core.storage import exceptions + + + class CacheTest:",Why a blank line here? +986,"@@ -14,6 +14,10 @@ class Subscription < ActiveRecord::Base + notifier.send_notifications + end + ++ def active? ++ deactivated_on.nil? ++ end ++ + private + + def self.subscriber_emails","I have a sense that this will actually eventually change to check the actual date so that subscriptions can be deactivated in the future. But I mention that here just to keep you in the loop. We should not make that change now, because it's not needed functionality." +987,"@@ -36,6 +36,10 @@ public class EnvironmentVariableDefaultProvider implements IDefaultValueProvider + + @Override + public String defaultValue(final ArgSpec argSpec) { ++ if (!argSpec.isOption()) { ++ return null; // skip default for positional params ++ } ++ + return envVarNames((OptionSpec) argSpec) + .map(environment::get) + .filter(Objects::nonNull)",What is the reasoning for using the negation of `isOption()` instead of simply using `isPositional()` to identify a positional param? +988,"@@ -1415,7 +1415,13 @@ void ProtocolGame::sendBasicData() + msg.addByte(0); + msg.add(0); + } ++ + msg.addByte(player->getVocation()->getClientId()); ++ ++ if (version >= 1100) { ++ msg.addByte(player->getVocation()->getId() != VOCATION_NONE ? 0x01 : 0x00); // prey data ++ } ++ + msg.add(0xFF); // number of known spells + for (uint8_t spellId = 0x00; spellId < 0xFF; spellId++) { + msg.addByte(spellId);",Why would you add those if client version min is set to 1100? +989,"@@ -7,12 +7,13 @@ + package snapshotsync + + import ( ++ reflect ""reflect"" ++ sync ""sync"" ++ + proto ""github.com/golang/protobuf/proto"" + protoreflect ""google.golang.org/protobuf/reflect/protoreflect"" + protoimpl ""google.golang.org/protobuf/runtime/protoimpl"" + emptypb ""google.golang.org/protobuf/types/known/emptypb"" +- reflect ""reflect"" +- sync ""sync"" + ) + + const (","You can delete this, it will now need to live in `gointerfaces` package" +990,"@@ -3,7 +3,7 @@ + <%= render 'previous_next_doc' %> + + +-<% @page_title = t('blacklight.search.show.title', :document_title => document_show_html_title, :application_name => application_name) -%> ++<% @page_title = t('blacklight.search.show.title', :document_title => document_show_html_title, :application_name => application_name).html_safe -%> + <% content_for(:head) { render_link_rel_alternates } -%> + <%# this should be in a partial -%> + ","Okay, I still don't understand why you have to add `html_safe` here, and it still seems like a very bad idea. It will allow html tags in the title, and keep Rails from escaping literal greater-than or less-than chars not intended as HTML tags. It ought to work to just let Rails do HTML-escaing as normal, without any manual `html_safe` or `strip_tags` or whatever. I am not clear on what problem you are trying to solve, why the straightfoward approach does not work." +991,"@@ -1435,6 +1435,8 @@ public class MessageList extends K9Activity implements MessageListFragmentListen + public void displayMessageSubject(String subject) { + if (mDisplayMode == DisplayMode.MESSAGE_VIEW) { + mActionBarSubject.setText(subject); ++ } else { ++ mActionBarSubject.showSubjectInMessageHeader(); + } + } + ",What is is subject when it's not the email subject. Why are we having to do this crap? What's calling this with an empty string? +992,"@@ -65,7 +65,7 @@ func NewProvider(opts ...ProviderOption) (*Provider, error) { + namedTracer: make(map[string]*tracer), + } + tp.config.Store(&Config{ +- DefaultSampler: ProbabilitySampler(defaultSamplingProbability), ++ DefaultSampler: AlwaysSample(), + IDGenerator: defIDGenerator(), + MaxAttributesPerSpan: DefaultMaxAttributesPerSpan, + MaxEventsPerSpan: DefaultMaxEventsPerSpan,",Could you also remove the `defaultSamplingProbability` constant from `sampling.go`? It seems to became unused with this change. +993,"@@ -63,9 +63,9 @@ func (s *svc) UpdateDeployment(ctx context.Context, clientset, cluster, namespac + } + + newDeployment := oldDeployment.DeepCopy() +- mergeLabelsAndAnnotations(newDeployment, fields) ++ mergeDeploymentLabelsAndAnnotations(newDeployment, fields) + +- patchBytes, err := generateDeploymentStrategicPatch(oldDeployment, newDeployment) ++ patchBytes, err := GenerateStrategicPatch(oldDeployment, newDeployment, appsv1.Deployment{}) + if err != nil { + return err + }",can you delete the `generateDeploymentStrategicPatch` function as well? +994,"@@ -61,7 +61,7 @@ class UnboundZmqEventBus implements EventBus { + return thread; + }); + +- LOG.info(String.format(""Connecting to %s and %s"", publishConnection, subscribeConnection)); ++ LOG.finest(String.format(""Connecting to %s and %s"", publishConnection, subscribeConnection)); + + sub = context.createSocket(SocketType.SUB); + sub.connect(publishConnection);",I'd keep this at `info` level... +995,"@@ -50,6 +50,10 @@ StatusOr LimitPushDownRule::transform( + const auto proj = static_cast(projGroupNode->node()); + const auto gn = static_cast(gnGroupNode->node()); + ++ DCHECK(graph::ExpressionUtils::isEvaluableExpr(limit->countExpr())); ++ if (!graph::ExpressionUtils::isEvaluableExpr(limit->countExpr())) { ++ return TransformResult::noTransform(); ++ } + int64_t limitRows = limit->offset() + limit->count(); + if (gn->limit() >= 0 && limitRows >= gn->limit()) { + return TransformResult::noTransform();",Don't use DCHECK to debug your code if it's the regular branch you need to handle. +996,"@@ -46,11 +46,6 @@ public interface AntlrNode extends Node { + throw new UnsupportedOperationException(""Out of scope for antlr current implementations""); + } + +- @Override +- default String getImage() { +- throw new UnsupportedOperationException(""Out of scope for antlr current implementations""); +- } +- + @Override + default void setImage(final String image) { + throw new UnsupportedOperationException(""Out of scope for antlr current implementations"");",You should return null here instead. Null is an acceptable default value for the image attribute. +997,"@@ -246,9 +246,14 @@ export function useErrorBoundary(cb) { + function flushAfterPaintEffects() { + afterPaintEffects.some(component => { + if (component._parentDom) { +- component.__hooks._pendingEffects.forEach(invokeCleanup); +- component.__hooks._pendingEffects.forEach(invokeEffect); +- component.__hooks._pendingEffects = []; ++ try { ++ component.__hooks._pendingEffects.forEach(invokeCleanup); ++ component.__hooks._pendingEffects.forEach(invokeEffect); ++ component.__hooks._pendingEffects = []; ++ } catch (e) { ++ options._catchError(e, component._vnode); ++ return true; ++ } + } + }); + afterPaintEffects = [];",react bails as well? +998,"@@ -7,7 +7,6 @@ namespace Shopsys\FrameworkBundle\Model\Security; + class Roles + { + public const ROLE_ADMIN = 'ROLE_ADMIN'; +- public const ROLE_ADMIN_AS_CUSTOMER = 'ROLE_ADMIN_AS_CUSTOMER'; + public const ROLE_LOGGED_CUSTOMER = 'ROLE_LOGGED_CUSTOMER'; + public const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN'; + ",Can you please tell me why you did this? +999,"@@ -168,9 +168,12 @@ module.exports = class Webcam extends Plugin { + this.opts.modes.indexOf('video-only') !== -1 || + this.opts.modes.indexOf('picture') !== -1 + ++ const videoConstraints = this.opts.videoConstraints ?? {} ++ videoConstraints.facingMode = this.opts.facingMode ++ + return { + audio: acceptsAudio, +- video: acceptsVideo ? { facingMode: this.opts.facingMode } : false ++ video: acceptsVideo ? videoConstraints : false + } + } + ",Reading this again it should prob prefer the `videoConstraints.facingMode` value over `facingMode` if the former was already set +1000,"@@ -1,7 +1,10 @@ + class Video < ActiveRecord::Base ++ extend FriendlyId ++ + belongs_to :watchable, polymorphic: true + + validates :published_on, presence: true ++ validates :slug, presence: true, uniqueness: true + validates :title, presence: true + validates :watchable_id, presence: true + validates :watchable_type, presence: true",There's a good bit of class-level stuff that's repeated in our various product types. Think it's worth extracting a...dare I say it...module? +1001,"@@ -79,7 +79,10 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil + // keep functions interoperable, pass int64 types as pointers to + // stack-allocated values. + // Use -wasm-abi=generic to disable this behaviour. +- if config.Options.WasmAbi == ""js"" && strings.HasPrefix(config.Triple(), ""wasm"") { ++ if config.Options.WasmAbi != """" { ++ config.Target.WasmAbi = config.Options.WasmAbi ++ } ++ if config.Target.WasmAbi == ""js"" { + err := transform.ExternalInt64AsPtr(mod) + if err != nil { + return err","Please do not modify the `config.Target` field, it should contain exactly what is extracted from the JSON files. Instead, you can either: * Add a getter to the `config` variable (`*compileopts.Config`), so you can simply call `config.WasmAbi()` to get the value. * Use a local variable instead. The getter would be slightly cleaner, as it matches the pattern of other configurations (`CGO_ENABLED`, `GC`, `NeedsStackObjects`, etc)." +1002,"@@ -159,6 +159,14 @@ func newTestEnv(inboundOptions []InboundOption, outboundOptions []OutboundOption + testRouter := newTestRouter(procedures) + + t := NewTransport() ++ if err := t.Start(); err != nil { ++ return nil, err ++ } ++ defer func() { ++ if err != nil { ++ err = multierr.Append(err, t.Stop()) ++ } ++ }() + + listener, err := net.Listen(""tcp"", ""127.0.0.1:0"") + if err != nil {",The nil check is not necessary for these. Append checks both sides for nil. +1003,"@@ -62,6 +62,7 @@ func main() { + trace.WithAttributes(attrs...), + trace.ChildOf(spanCtx), + ) ++ span.SetAttributes(entries...) + defer span.End() + + span.AddEvent(ctx, ""handling this..."")","Shouldn't we instead have the SDK apply these, internally? I.e., I would expect to see the dctx entries included in the span as first-class distributed correlations, not as span attributes." +1004,"@@ -60,5 +60,12 @@ func (t *topologyAPI) GetTopology(ctx context.Context, req *topologyv1.GetTopolo + } + + func (t *topologyAPI) SearchTopology(ctx context.Context, req *topologyv1.SearchTopologyRequest) (*topologyv1.SearchTopologyResponse, error) { +- return nil, errors.New(""not implemented"") ++ resources, err := t.topology.SearchTopology(ctx, req) ++ if err != nil { ++ return nil, err ++ } ++ ++ return &topologyv1.SearchTopologyResponse{ ++ Resources: resources, ++ }, nil + }",nit: rename this in proto and update impl to `Search` to avoid stutter +1005,"@@ -78,7 +78,8 @@ class SliderController extends AdminBaseController + ->from(SliderItem::class, 's') + ->where('s.domainId = :selectedDomainId') + ->setParameter('selectedDomainId', $this->adminDomainTabsFacade->getSelectedDomainId()) +- ->orderBy('s.position'); ++ ->orderBy('s.position') ++ ->addOrderBy('s.id'); + $dataSource = new QueryBuilderDataSource($queryBuilder, 's.id'); + + $grid = $this->gridFactory->create('sliderItemList', $dataSource);",is it necessary to order by id as a second ordering? this will take place only when several new slider items are created without reordering (position is then null). Wouldn't be better to recalculate position after creating a new item? (right now items with null in position behave differently in administration and on frontend) +1006,"@@ -18,8 +18,10 @@ import ( + ) + + var ( +- claimFromRewardingFundBaseGas = uint64(10000) +- claimFromRewardingFundGasPerByte = uint64(100) ++ // ClaimFromRewardingFundBaseGas represents the base intrinsic gas for claimFromRewardingFund ++ ClaimFromRewardingFundBaseGas = uint64(10000) ++ // ClaimFromRewardingFundGasPerByte represents the claimFromRewardingFund payload gas per uint ++ ClaimFromRewardingFundGasPerByte = uint64(100) + ) + + // ClaimFromRewardingFund is the action to claim reward from the rewarding fund",`ClaimFromRewardingFundBaseGas` is a global variable (from `gochecknoglobals`) +1007,"@@ -89,9 +89,11 @@ namespace RDKit { + } + PyObject *GetSubstructMatch(const ROMol &mol, const ROMol &query,bool useChirality=false, + bool useQueryQueryMatches=false){ +- NOGIL gil; + MatchVectType matches; +- SubstructMatch(mol,query,matches,true,useChirality,useQueryQueryMatches); ++ { ++ NOGIL gil; ++ SubstructMatch(mol,query,matches,true,useChirality,useQueryQueryMatches); ++ } + return convertMatches(matches); + } + ",How about modifying the NOGIL definition so that it only does anything if the thread safety flag (RDK_BUILD_THREADSAFE_SSS) is set? +1008,"@@ -29,6 +29,11 @@ type chainState interface { + LatestState(ctx context.Context) (state.Tree, error) + } + ++// BlockTimer defines a interface to a struct that can give the current block height. ++type BlockTimer interface { ++ BlockHeight() (uint64, error) ++} ++ + // PublishFunc is a function the Sender calls to publish a message to the network. + type PublishFunc func(topic string, data []byte) error + ",blockheighter would be more clear +1009,"@@ -949,5 +949,15 @@ void OptimizerUtils::copyIndexScanData(const nebula::graph::IndexScan* from, + to->setFilter(from->filter() == nullptr ? nullptr : from->filter()->clone()); + } + ++Status OptimizerUtils::compareAndSwapBound(std::pair& a, std::pair& b) { ++ if (a.first > b.first) { ++ std::swap(a, b); ++ } else if (a.first < b.first) { // do nothing ++ } else if (a.second > b.second) { ++ std::swap(a, b); ++ } ++ return Status::OK(); ++} ++ + } // namespace graph + } // namespace nebula",This is so weird as a utility function. +1010,"@@ -58,7 +58,8 @@ func TestPlanQuery(t *testing.T) { + return m + } + +- cmpopt := cmp.AllowUnexported(dynamodb.ScanInput{}, dynamodb.QueryInput{}, dynamodb.AttributeValue{}) ++ // Ignores the ConsistentRead field from both QueryInput and ScanInput. ++ cmpopt := cmp.FilterPath(func(p cmp.Path) bool { return p.Last().String() == "".ConsistentRead"" }, cmp.Ignore()) + + for _, test := range []struct { + desc string",Why? What would happen if you did not? +1011,"@@ -752,7 +752,9 @@ public class SmartStore { + String[] pathElements = path.split(""[.]""); + Object o = soup; + for (String pathElement : pathElements) { +- o = ((JSONObject) o).opt(pathElement); ++ if (o != null) { ++ o = ((JSONObject) o).opt(pathElement); ++ } + } + return o; + }",Unrelated bugfix for NPE. +1012,"@@ -387,7 +387,7 @@ class AdminController extends Controller + throw new \Exception(sprintf('The ""%s"" property is not a switchable toggle.', $propertyName)); + } + +- if (!$propertyMetadata['canBeSet']) { ++ if (!$propertyMetadata['isWritable']) { + throw new \Exception(sprintf('It\'s not possible to toggle the value of the ""%s"" boolean property of the ""%s"" entity.', $propertyName, $this->entity['name'])); + } + ",What if some extended the `AdminController` and had a check for the old option name? Could that be a valid use case? +1013,"@@ -524,6 +524,17 @@ + dataType: ""json"" + }); + }, ++ fetchSegmentMap: function() { ++ return CV.$.ajax({ ++ type: ""GET"", ++ url: countlyCommon.API_PARTS.data.r + '/data-manager/event-segment', ++ data: { ++ ""app_id"": countlyCommon.ACTIVE_APP_ID, ++ ""preventRequestAbort"": true, ++ }, ++ dataType: ""json"" ++ }); ++ }, + fetchRefreshSelectedEventsData: function(context) { + return CV.$.ajax({ + type: ""GET"",","This will be only available when data-manager is enabled, is there a fallback in case data manager is disabled?" +1014,"@@ -219,7 +219,7 @@ func (o *deploySvcOpts) generateWorkerServiceRecommendedActions() { + retrieveEnvVarCode := ""const eventsQueueURI = process.env.COPILOT_QUEUE_URI"" + actionRetrieveEnvVar := fmt.Sprintf( + `Update %s's code to leverage the injected environment variable ""COPILOT_QUEUE_URI"". +-In JavaScript you can write %s.`, ++ In JavaScript you can write %s.`, + o.name, + color.HighlightCode(retrieveEnvVarCode), + )",Do you think we want to move the call to `generateWorkerServiceRecommendedActions` inside `RecommandedActions()`? +1015,"@@ -3277,7 +3277,7 @@ bool CoreChecks::PreCallValidateGetQueryPoolResults(VkDevice device, VkQueryPool + VkQueryResultFlags flags) const { + if (disabled.query_validation) return false; + bool skip = false; +- skip |= ValidateQueryPoolStride(""VUID-vkGetQueryPoolResults-flags-00814"", ""VUID-vkGetQueryPoolResults-flags-00815"", stride, ++ skip |= ValidateQueryPoolStride(""VUID-vkGetQueryPoolResults-flags-02827"", ""VUID-vkGetQueryPoolResults-flags-00815"", stride, + ""dataSize"", dataSize, flags); + skip |= ValidateGetQueryPoolResultsFlags(queryPool, flags); + skip |= ValidateGetQueryPoolResultsQueries(queryPool, firstQuery, queryCount);","The VUIDs in this area are not great, but I think `ValidateQueryPoolStride` should probably be skipped if the query pool was created with type `VK_QUERY_TYPE_PERFORMANCE_QUERY`. VUID-02828 might be a better fit, but again, the existing VUIDs step on each other so it requires a bit of interpretation." +1016,"@@ -74,11 +74,12 @@ namespace Nethermind.Store + db[key.ToBigEndianByteArrayWithoutLeadingZeros()] = value; + } + +- public static byte[] Get(this IDb db, long key) +- { +- return db[key.ToBigEndianByteArrayWithoutLeadingZeros()]; +- } +- ++ public static byte[] Get(this IDb db, long key) => db[key.ToBigEndianByteArrayWithoutLeadingZeros()]; ++ ++ public static byte[] ToDbKey(this long key) => key.ToBigEndianByteArrayWithoutLeadingZeros(); ++ ++ public static byte[] ToDbKey(this Keccak key) => key.Bytes; ++ + public static void Delete(this IDb db, long key) + { + db.Remove(key.ToBigEndianByteArrayWithoutLeadingZeros());",Iguess you should use ToDbKey here +1017,"@@ -179,16 +179,7 @@ func (x *blockIndexer) DeleteTipBlock(blk *block.Block) error { + func (x *blockIndexer) Height() (uint64, error) { + x.mutex.RLock() + defer x.mutex.RUnlock() +- +- index, err := db.GetCountingIndex(x.kvStore, totalBlocksBucket) +- if err != nil { +- if errors.Cause(err) == db.ErrBucketNotExist || errors.Cause(err) == db.ErrNotExist { +- // counting index does not exist yet +- return 0, nil +- } +- return 0, err +- } +- return index.Size() - 1, nil ++ return x.tbk.Size() - 1, nil + } + + // GetBlockHash returns the block hash by height","x.tbk is the ""index"" below, and is done in Start()" +1018,"@@ -8,6 +8,7 @@ namespace Datadog.Trace.Util + /// + internal static class DomainMetadata + { ++ private const string IsAppInsightKey = ""DD_IsAppInsight""; + private const string UnknownName = ""unknown""; + private static Process _currentProcess; + private static bool _processDataPoisoned;","Do we already have a convention for this? If not, would we consider ""DataDog.IsAppInsights"". And then use ""DataDog."" prefix for all this settings, environment variables etc..? Such settings are, essentially, public APIs because they may conflict with customer data. Regardless of that , AppInsights has an s at the end :)" +1019,"@@ -95,6 +95,16 @@ static int cb_firehose_init(struct flb_output_instance *ins, + ctx->time_key_format = DEFAULT_TIME_KEY_FORMAT; + } + ++ tmp = flb_output_get_property(""log_key"", ins); ++ if (tmp) { ++ ctx->log_key = tmp; ++ } ++ ++ if (ctx->log_key && ctx->time_key) { ++ flb_plg_error(ctx->ins, ""'time_key' and 'log_key' can not be used together""); ++ goto error; ++ } ++ + tmp = flb_output_get_property(""endpoint"", ins); + if (tmp) { + ctx->custom_endpoint = FLB_TRUE;",this assignment is not necessary if the offsetof() is used in the configmap +1020,"@@ -268,11 +268,6 @@ func (p *Protocol) claimFromAccount(sm protocol.StateManager, addr address.Addre + balance := big.NewInt(0).Sub(acc.balance, amount) + if balance.Cmp(big.NewInt(0)) < 0 { + return errors.New(""no enough available balance"") +- } else if balance.Cmp(big.NewInt(0)) == 0 { +- // If the account balance is cleared, delete if from the store +- if err := p.deleteState(sm, accKey); err != nil { +- return err +- } + } else { + acc.balance = balance + if err := p.putState(sm, accKey, &acc); err != nil {",I'd rather leave a TODO here at least. +1021,"@@ -115,10 +115,10 @@ class BatchViewTest(BaseWebTest, unittest.TestCase): + request = {""path"": ""/mushrooms/""} # trailing slash + body = {""requests"": [request]} + resp = self.app.post_json(""/batch"", body, headers=self.headers) +- collection = resp.json[""responses""][0] +- self.assertEqual(collection[""status""], 200) +- self.assertEqual(collection[""path""], ""/v0/mushrooms"") +- self.assertEqual(collection[""body""], {""data"": []}) ++ objects = resp.json[""responses""][0] ++ self.assertEqual(objects[""status""], 200) ++ self.assertEqual(objects[""path""], ""/v0/mushrooms"") ++ self.assertEqual(objects[""body""], {""data"": []}) + + def test_body_is_transmitted_during_redirect(self): + request = {",Shouldn't this be `resource`? +1022,"@@ -37,13 +37,12 @@ namespace { + /** CPU implementation of evaluation layer forward prop. */ + void fp_cpu(lbann_comm& comm, + const AbsDistMat& input, +- DataType& value, +- Al::request& req) { ++ DataType& value) { + const auto& local_input = input.LockedMatrix(); + const auto& local_height = local_input.Height(); + const auto& local_width = local_input.Width(); + const auto& mini_batch_size = input.Width(); +- value = DataType(0); ++ value = 0; + #pragma omp parallel for reduction(+:value) collapse(2) + for (El::Int col = 0; col < local_width; ++col) { + for (El::Int row = 0; row < local_height; ++row) {",Why does this become blocking for the CPU path? Shouldn't it remain independent of the GPU path? +1023,"@@ -24,7 +24,7 @@ module Travis + sh.export 'TRAVIS_RUBY_VERSION', config[:rvm], echo: false if rvm? + end + +- def setup ++ def configure + super + setup_rvm if rvm? + end",Do we need to change occurences where `setup` was called before? +1024,"@@ -61,6 +61,16 @@ func (a *API) resolveReferences() { + o.ErrorRefs[i].Shape.IsError = true + } + } ++ ++ // TODO put this somewhere better ++ for _, s := range a.Shapes { ++ switch s.Type { ++ case ""list"": ++ s.MemberRef.Shape.UsedInList = true ++ case ""map"": ++ s.ValueRef.Shape.UsedInMap = true ++ } ++ } + } + + // A referenceResolver provides a way to resolve shape references to",Is this TODO still valid? Or are we going to put this somewhere else later? +1025,"@@ -15,12 +15,17 @@ def generate_data(test_user_id, user_name, from_ts, num_records): + test_data = [] + artist_msid = str(uuid.uuid4()) + +- for i in range(num_records): ++ if (from_ts == None): #check for playing now listens ++ timestamp = None ++ else: + from_ts += 1 # Add one second ++ timestamp = datetime.utcfromtimestamp(from_ts) ++ ++ for i in range(num_records): + item = Listen( + user_name=user_name, + user_id=test_user_id, +- timestamp=datetime.utcfromtimestamp(from_ts), ++ timestamp= timestamp, + artist_msid=artist_msid, + recording_msid=str(uuid.uuid4()), + data={",We generally don't do parantheses in if conditions in Python. :) this could be better written as `if from_ts is None` +1026,"@@ -460,9 +460,13 @@ void tm_process_req_requestregioninfo(CTmTxMessage * pp_msg) + TM_Txid_legacy lv_transid; + } u; + +- char tname[2000], ername[50], rname[100], offline[20], regid[200], hostname[200], port[100]; ++ char tname[2000]; ++ tname[299] = '\0'; ++/* ++ char ername[50], rname[100], offline[20], regid[200], hostname[200], port[100]; + tname[299] = '\0', ername[49] = '\0', rname[99] = '\0', offline[19] = '\0'; + regid[199]= '\0', hostname[199]='\0', port[99]='\0'; ++*/ + + TMTrace(2, (""tm_process_req_requestregioninfo ENTRY.\n"")); + HashMapArray* map = HbaseTM_process_request_regions_info();",Odd that we'd set just element 299 of a 2000-byte buffer to null. But I see that this is the way it was before. +1027,"@@ -28,3 +28,9 @@ type PeerAdder interface { + type ClosestPeerer interface { + ClosestPeer(addr swarm.Address) (peerAddr swarm.Address, err error) + } ++ ++// ScoreFunc is implemented by components that need to score peers in a different way than XOR distance. ++type ScoreFunc func(peer swarm.Address) (score float32) ++ ++// EachPeerFunc is a callback that is called with a peer and its PO ++type EachPeerFunc func(swarm.Address, uint8) (stop, jumpToNext bool, err error)",ScoreFunc is not used in this PR. Maybe to add it later when needed? +1028,"@@ -171,9 +171,9 @@ func customResponseForwarder(ctx context.Context, w http.ResponseWriter, resp pr + http.SetCookie(w, cookie) + } + +- if redirects := md.HeaderMD.Get(""Location""); len(redirects) > 0 { +- w.Header().Set(""Location"", redirects[0]) +- ++ // Redirect if it's the browser (non-XHR). ++ redirects := md.HeaderMD.Get(""Location"") ++ if len(redirects) > 0 && isBrowser(copyRequestHeadersFromResponseWriter(w)) { + code := http.StatusFound + if st := md.HeaderMD.Get(""Location-Status""); len(st) > 0 { + headerCodeOverride, err := strconv.Atoi(st[0])",super nit: I think this might be easier to read as `requestHeadersFromResponseWriter` +1029,"@@ -4,12 +4,8 @@ + * (found in the LICENSE.Apache file in the root directory) + */ + #include +-#include +-#include +-#include +-#include +-#include ""common/concurrent/Barrier.h"" +-#include ""common/thread/GenericThreadPool.h"" ++#include ""concurrent/Barrier.h"" ++#include ""thread/GenericThreadPool.h"" + + namespace vesoft { + namespace concurrent {","Need to include ""common/base/Base.h"" in front of this line" +1030,"@@ -1,6 +1,5 @@ + import getRole from '../aria/get-role'; +-import matches from '../matches/matches'; +-import nativeElementType from './native-element-type'; ++import getElementSpec from '../standards/get-element-spec'; + import nativeTextMethods from './native-text-methods'; + + /**",Changes in this file should go into a separate PR. +1031,"@@ -243,10 +243,15 @@ public class PhpSurfaceNamer extends SurfaceNamer { + if (token.equals(InitFieldConfig.RANDOM_TOKEN)) { + stringParts.add(""time()""); + } else { +- stringParts.add(""\"""" + token + ""\""""); ++ stringParts.add(quoted(token)); + } + } + } + return Joiner.on("". "").join(stringParts); + } ++ ++ @Override ++ public String quoted(String text) { ++ return ""\'"" + text + ""\'""; ++ } + }",Please ensure that this will not start putting single quotes where double quotes are expected. +1032,"@@ -68,7 +68,7 @@ type Manager struct { + } + + // ProvideConfig provides the config for consumer +-func (manager *Manager) ProvideConfig(publicKey json.RawMessage, pingerPort func(int) int) (session.ServiceConfiguration, session.DestroyCallback, error) { ++func (manager *Manager) ProvideConfig(publicKey json.RawMessage, pingerPort func(int, int) int) (session.ServiceConfiguration, session.DestroyCallback, error) { + key := &wg.ConsumerConfig{} + err := json.Unmarshal(publicKey, key) + if err != nil {","`ProvideConfig` was changed, looks like it will not compile for windows, and should be changed too." +1033,"@@ -76,9 +76,8 @@ func Search(ctx *context.APIContext) { + }) + } + +-// https://github.com/gogits/go-gogs-client/wiki/Repositories#list-your-repositories +-func ListMyRepos(ctx *context.APIContext) { +- ownRepos, err := models.GetUserRepositories(ctx.User.ID, true, 1, ctx.User.NumRepos) ++func listUserRepos(ctx *context.APIContext, u *models.User) { ++ ownRepos, err := models.GetUserRepositories(u.ID, true, 1, u.NumRepos) + if err != nil { + ctx.Error(500, ""GetRepositories"", err) + return","This does not look right, you're listing all private repositories.." +1034,"@@ -20,4 +20,6 @@ C2::Application.routes.draw do + get 'bookmarklet', to: redirect('bookmarklet.html') + get ""/498"", :to => ""errors#token_authentication_error"" + ++ match ""*path"" => ""application#xss_options_request"", :via => :options ++ + end",An OPTIONS request should respond from _any_ path? Seems weird to me... +1035,"@@ -40,6 +40,8 @@ class MediaAdmin extends Admin + ->add('category', null, array( + 'show_filter' => false, + )) ++ ->add('width') ++ ->add('height') + ; + + $providers = array();",you need to add the content type +1036,"@@ -12,6 +12,14 @@ namespace Datadog.Trace + { + private static Task _traceAgentMonitor; + private static Task _dogStatsDMonitor; ++ private static Process _traceAgentProcess; ++ private static Process _dogStatsProcess; ++ ++ public static void StopSubProcesses() ++ { ++ SafelyKillProcess(_traceAgentProcess, ""Failed to halt the sub-process trace agent""); ++ SafelyKillProcess(_dogStatsProcess, ""Failed to halt the sub-process stats agent""); ++ } + + public static void StartStandaloneAgentProcessesWhenConfigured() + {",Do we need to distinguish between these two processes? I'm thinking maybe we can have a list of processes and treat them all equally. +1037,"@@ -61,8 +61,8 @@ callee_info_t default_callee_info; + int + get_clean_call_switch_stack_size(void) + { +-#ifdef AARCH64 +- /* Stack size needs to be 16 byte aligned on ARM */ ++#if defined(AARCH64) || defined(X64) ++ /* Stack size needs to be 16 byte aligned on ARM and x64. */ + return ALIGN_FORWARD(sizeof(priv_mcontext_t), 16); + #else + return sizeof(priv_mcontext_t);","This is used only for out-of-line -- so yes this seems right to do for x64. Inlined is aligned separately at the end of prepare_for_clean_call(). There the ifdef is x86_64 or MACOS -- no ARM, why not? Also, please add || MACOS here to match the inlined." +1038,"@@ -271,7 +271,8 @@ final class MySQLSpanStore implements SpanStore { + .selectDistinct(ZIPKIN_SPANS.NAME) + .from(ZIPKIN_SPANS) + .join(ZIPKIN_ANNOTATIONS) +- .on(ZIPKIN_SPANS.TRACE_ID.eq(ZIPKIN_ANNOTATIONS.TRACE_ID)) ++ .on(ZIPKIN_SPANS.TRACE_ID_HIGH.eq(ZIPKIN_ANNOTATIONS.TRACE_ID_HIGH)) ++ .and(ZIPKIN_SPANS.TRACE_ID.eq(ZIPKIN_ANNOTATIONS.TRACE_ID)) + .and(ZIPKIN_SPANS.ID.eq(ZIPKIN_ANNOTATIONS.SPAN_ID)) + .where(ZIPKIN_ANNOTATIONS.ENDPOINT_SERVICE_NAME.eq(serviceName)) + .orderBy(ZIPKIN_SPANS.NAME)",guess I'm wondering if this needs to be refactored to use Schema.joinCondition() or similar? +1039,"@@ -53,6 +53,7 @@ module Beaker + class_option :'xml-time-order', :type => :boolean, :group => 'Beaker run' + class_option :'debug-errors', :type => :boolean, :group => 'Beaker run' + class_option :'exec_manual_tests', :type => :boolean, :group => 'Beaker run' ++ class_option :'test-tag-exclude', :type => :string, :group => 'Beaker run' + + # The following are listed as deprecated in beaker --help, but needed now for + # feature parity for beaker 3.x.",Does it make sense to restrict this option to `exec` only? You could add it specific to that subcommand using the `method_option`...method. There's an example of it for hosts in the `init` function. +1040,"@@ -143,7 +143,10 @@ namespace OpenTelemetry.Context.Propagation + break; + } + +- if (NameValueHeaderValue.TryParse(pair, out NameValueHeaderValue baggageItem)) ++ var decodedPair = WebUtility.UrlDecode(pair); ++ var escapedPair = string.Join(""="", decodedPair.Split('=').Select(Uri.EscapeDataString)); ++ ++ if (NameValueHeaderValue.TryParse(escapedPair, out NameValueHeaderValue baggageItem)) + { + if (string.IsNullOrEmpty(baggageItem.Name) || string.IsNullOrEmpty(baggageItem.Value)) + {","This is very expensive (lots of allocations, lots of data copying). Could we do something like check IndexOf('%') and bypass if no hit?" +1041,"@@ -55,10 +55,17 @@ public class PvPUtil + public static boolean isAttackable(Client client, Player player) + { + int wildernessLevel = 0; +- if (!(client.getVar(Varbits.IN_WILDERNESS) == 1 || WorldType.isPvpWorld(client.getWorldType()))) ++ if (!(client.getVar(Varbits.IN_WILDERNESS) == 1 ++ || WorldType.isPvpWorld(client.getWorldType()) ++ || client.getWorldType().contains(WorldType.DEADMAN) ++ )) + { + return false; + } ++ if (client.getWorldType().contains(WorldType.DEADMAN)) ++ { ++ return true; ++ } + if (WorldType.isPvpWorld(client.getWorldType())) + { + if (client.getVar(Varbits.IN_WILDERNESS) != 1)",This should be `WorldType.isDeadmanWorld(client.getWorldType())` to be inline with the other WorldType calls. +1042,"@@ -600,11 +600,11 @@ class SABLRetinaHead(BaseDenseHead, BBoxTestMixin): + bbox_cls_pred.contiguous(), + bbox_reg_pred.contiguous() + ] +- bboxes, confids = self.bbox_coder.decode( ++ bboxes, confidences = self.bbox_coder.decode( + anchors.contiguous(), bbox_preds, max_shape=img_shape) + mlvl_bboxes.append(bboxes) + mlvl_scores.append(scores) +- mlvl_confids.append(confids) ++ mlvl_confids.append(confidences) + mlvl_bboxes = torch.cat(mlvl_bboxes) + if rescale: + mlvl_bboxes /= mlvl_bboxes.new_tensor(scale_factor)",do we also need to change `mlvl_confid` -> `mlvl_confidences`> +1043,"@@ -125,7 +125,8 @@ type Config struct { + MetadataAddr string `config:""hostname;127.0.0.1;die-on-fail""` + MetadataPort int `config:""int(0,65535);8775;die-on-fail""` + +- InterfacePrefix string `config:""iface-list;cali;non-zero,die-on-fail""` ++ InterfacePrefix string `config:""iface-list;cali;non-zero,die-on-fail""` ++ InterfaceExclude string `config:""iface-list;kube-ipvs0""` + + ChainInsertMode string `config:""oneof(insert,append);insert;non-zero,die-on-fail""` + DefaultEndpointToHostAction string `config:""oneof(DROP,RETURN,ACCEPT);DROP;non-zero,die-on-fail""`","I feel slightly that InterfaceExclude is not a clear name - bearing in mind that our config names are, to some extent, an external API. From an external point of view, a clearer name might be IPVSInterfaces. Then it would obviously make sense for the value to be something like 'kube-ipvs0', and it would be a matter of Felix's internal implementation that we choose to exclude those interfaces from our monitoring. Alternatively, if we want to keep this at a level that is more general than just IPVS, perhaps 'UnmonitoredInterfaces'? WDYT?" +1044,"@@ -180,7 +180,7 @@ def transform_path(path): + path = utils.expand_windows_drive(path) + # Drive dependent working directories are not supported, e.g. + # E:filename is invalid +- if re.match(r'[A-Z]:[^\\]', path, re.IGNORECASE): ++ if re.fullmatch(r'[A-Z]:[^\\]', path, re.IGNORECASE): + return None + # Paths like COM1, ... + # See https://github.com/qutebrowser/qutebrowser/issues/82","This should be `re.search` with a `^` anchor added to the regex, as what we want here is really any path starting with something like `E:`." +1045,"@@ -108,6 +108,14 @@ func determineResourceHealth(key ResourceKey, obj *unstructured.Unstructured) (s + return determineClusterRoleHealth(obj) + case KindClusterRoleBinding: + return determineClusterRoleBindingHealth(obj) ++ case KindVirtualService: ++ return determineVirtualService(obj) ++ case KindDestinationRule: ++ return determineDestinationRule(obj) ++ case KindGateway: ++ return determineGateway(obj) ++ case KindServiceEntry: ++ return determineServiceEntry(obj) + default: + desc = ""Unimplemented or unknown resource"" + return","Since `IsKubernetesBuiltInResource` at L69 returns false due to lack `networking.istio.io/v1alpha3` in `builtInApiVersions` within `pkg/app/piped/cloudprovider/kubernetes/resourcekey.go`, it will never reach this point." +1046,"@@ -40,7 +40,7 @@ import ( + // themselves. + func RunEndToEndTest(ctx context.Context, t *testing.T, exp *otlpmetric.Exporter, mcMetrics Collector) { + selector := simple.NewWithInexpensiveDistribution() +- proc := processor.New(selector, exportmetric.StatelessExportKindSelector()) ++ proc := processor.NewFactory(selector, exportmetric.StatelessExportKindSelector()) + cont := controller.New(proc, controller.WithExporter(exp)) + require.NoError(t, cont.Start(ctx)) + ",Does codecov not run this test? Not sure how else it would not be covered. +1047,"@@ -30,8 +30,9 @@ func main() { + + // rootCmd represents the base command when called without any subcommands + var rootCmd = &cobra.Command{ +- Use: ""multisend [command]"", +- Args: cobra.ExactArgs(1), ++ Use: ""multisend 'JSON_DATA'"", ++ Short: ""multisend bytecode generator"", ++ Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + output, err := multiSend(args) + if err == nil {",can we add some sample of JSON_DATA format in the usage? +1048,"@@ -25,13 +25,13 @@ namespace Datadog.Trace.Logging + _logProvider = logProvider; + } + +- public void Initialize(IScopeManager scopeManager, string defaultServiceName, string version, string env) ++ public void Initialize(string defaultServiceName, string version, string env) + { + _versionProperty = version; + _environmentProperty = env; + _serviceProperty = defaultServiceName; +- _traceIdProperty = CreateTracerProperty(scopeManager, t => t.Active?.Span.TraceId.ToString()); +- _spanIdProperty = CreateTracerProperty(scopeManager, t => t.Active?.Span.SpanId.ToString()); ++ _traceIdProperty = CreateTracerProperty(() => Tracer.Instance.DistributedSpanContext?[HttpHeaderNames.TraceId]); ++ _spanIdProperty = CreateTracerProperty(() => Tracer.Instance.DistributedSpanContext?[HttpHeaderNames.ParentId]); + } + + public IDisposable Register()",Using `Tracer.Instance` in here is problematic for testing It will likely cause some other tests to break I think - that's why we started passing in `IScopeManager` EDIT: I see you used `[TracerRestore]` - maybe that'll be enough! +1049,"@@ -22,7 +22,10 @@ import javax.annotation.Nullable; + */ + @AutoValue + public abstract class InitFieldConfig { ++ public static final String projectIdVariableName = ""project_id""; ++ + private static final String randomValueToken = ""$RANDOM""; ++ private static final String projectIdToken = ""$PROJECT_ID""; + + public abstract String fieldPath(); + ",make all of these `static final` fields UPPER_SNAKE - they are constants. +1050,"@@ -3298,7 +3298,8 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi + + // If this is a DoT, use DoT Shielding... + if (iBuffTic) { +- damage -= (damage * itembonuses.DoTShielding / 100); ++ int total_dotshielding = itembonuses.DoTShielding + itembonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] + aabonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT]; ++ damage -= (damage * total_dotshielding / 100); + + if (spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT]) { + slot = spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_BUFFSLOT];","No possible chance for weird overflows here, right?" +1051,"@@ -39,9 +39,13 @@ import org.apache.lucene.search.Weight; + * @lucene.experimental + */ + public abstract class ValueSourceScorer extends Scorer { ++ // Fixed cost for a single iteration of the TwoPhaseIterator instance ++ private static final int DEF_COST = 5; ++ + protected final FunctionValues values; + private final TwoPhaseIterator twoPhaseIterator; + private final DocIdSetIterator disi; ++ private float externallyMutableCost; + + protected ValueSourceScorer(Weight weight, LeafReaderContext readerContext, FunctionValues values) { + super(weight);",Or we could use a Float object to more clearly show as user-settable via non-null? +1052,"@@ -107,7 +107,7 @@ namespace Nethermind.Merge.Plugin.Handlers.V1 + + if (headUpdated && shouldUpdateHead) + { +- _poSSwitcher.ForkchoiceUpdated(newHeadBlock!.Header); ++ _poSSwitcher.ForkchoiceUpdated(newHeadBlock!.Header, finalizedHeader); + _stateProvider.ResetStateTo(newHeadBlock.StateRoot!); + if (_logger.IsInfo) _logger.Info($""Block {forkchoiceState.HeadBlockHash} was set as head""); + }",finalizedHeader should be saved in FinalizationManager when we have FinalizationBlockHash != Keccak.Zero +1053,"@@ -48,6 +48,7 @@ func AddDiskImportSteps(w *daisy.Workflow, dataDiskInfos []ovfutils.DiskInfo) { + + setupDataDiskStepName := fmt.Sprintf(""setup-data-disk-%v"", dataDiskIndex) + diskImporterDiskName := fmt.Sprintf(""disk-importer-%v"", dataDiskIndex) ++ scratchDiskDiskName := fmt.Sprintf(""disk-importer-scratch-%s-%v"", w.ID(), dataDiskIndex) + + setupDataDiskStep := daisy.NewStep(setupDataDiskStepName, w, time.Hour) + setupDataDiskStep.CreateDisks = &daisy.CreateDisks{","Not using ExactName: true would remove the need for manually adding workflow ID as it would be added automatically by Daisy. E.g. 'disk-importer-2-import-ovf-7mn7h' was created from diskImporterDiskName above even though only 'disk-importer-2' was specified. ExactName: true should be used for resources that shouldn't include any temp prefix/suffix, such as disks that will be permanently attached to a created instance. Scratch disk is not one of them." +1054,"@@ -8469,8 +8469,13 @@ defaultdict(, {'col..., 'col...})] + 'For argument ""inplace"" expected type bool, received type {}.' + .format(type(inplace).__name__)) + +- sdf = self._sdf.filter(expr) +- internal = self._internal.copy(sdf=sdf) ++ data_columns = [label[0] for label in self._internal.column_labels] ++ sdf = self._sdf.select(self._internal.index_scols ++ + [scol.alias(col) for scol, col ++ in zip(self._internal.column_scols, data_columns)]) \ ++ .filter(expr) ++ internal = self._internal.copy(sdf=sdf, ++ column_scols=[scol_for(sdf, col) for col in data_columns]) + + if inplace: + self._internal = internal","If we support multi-index column later, we need to rename to fit the pandas' requirement." +1055,"@@ -0,0 +1,11 @@ ++package aws ++ ++// JSONValue is a representation of a grab bag type that will be marshaled ++// into a json string. This type can be used just like any other map. ++// ++// Example: ++// values := JSONValue{ ++// ""Foo"": ""Bar"", ++// } ++// values[""Baz""] = ""Qux"" ++type JSONValue map[string]interface{}","I'm not sure this is really needed. JSONValue type can be used the same as a map as far as operators go, including range. I'd leave this out for now unless there is a strong reason to keep it." +1056,"@@ -724,6 +724,7 @@ void Container::internalAddThing(uint32_t, Thing* thing) + + void Container::startDecaying() + { ++ Item::startDecaying(); + for (Item* item : itemlist) { + item->startDecaying(); + }",sorry for nitpicking but I would love a new line under this line +1057,"@@ -21,5 +21,5 @@ package node + type OptionsTransactor struct { + TransactorEndpointAddress string + RegistryAddress string +- AccountantID string ++ ChannelImplementation string + }","ChannelImplementation field naming is not clear, is it some kind of standard? Maybe it can be named ChannelID?" +1058,"@@ -67,4 +67,11 @@ public interface ActionsProvider { + default ExpireSnapshots expireSnapshots(Table table) { + throw new UnsupportedOperationException(this.getClass().getName() + "" does not implement expireSnapshots""); + } ++ ++ /** ++ * Instantiates an action to remove all the files referenced by given metadata location. ++ */ ++ default RemoveFiles removeFiles(String metadataLocation) { ++ throw new UnsupportedOperationException(this.getClass().getName() + "" does not implement expireSnapshots""); ++ } + }",Looks like there is a typo: `expireSnapshots` -> `removeFiles` or whatever name we go with. +1059,"@@ -31,7 +31,7 @@ public abstract class IntraFeedSortDialog { + + int idxCurrentSort = -1; + for (int i = 0; i < values.length; i++) { +- if (currentSortOrder == values[i]) { ++ if (currentSortOrder == values[i] || currentSortOrder == null) { + idxCurrentSort = i; + break; + }",Thanks for looking into this. I think it looks a bit strange to have this check inside the for loop. Wouldn't it also work to initialize `idxCurrentSort` with 0 instead? +1060,"@@ -72,6 +72,8 @@ public class Notification { + public static final int OMNIPOD_POD_NOT_ATTACHED = 59; + public static final int CARBS_REQUIRED = 60; + public static final int IMPORTANCE_HIGH = 2; ++ public static final int OMNIPOD_POD_SUSPENDED = 61; ++ public static final int OMNIPOD_POD_ALERTS_UPDATED = 62; + + public static final String CATEGORY_ALARM = ""alarm""; + ",Just a small ordering thing: Could you please bring `IMPORTANCE_HIGH` to the bottom and maybe even have one line between it and the Notification IDs? +1061,"@@ -48,7 +48,7 @@ void prepareMolForDrawing(RWMol &mol, bool kekulize, bool addChiralHs, + if (kekulize) { + try { + MolOps::Kekulize(mol, false); // kekulize, but keep the aromatic flags! +- } catch(const RDKit::AtomKekulizeException &e) { ++ } catch (const RDKit::AtomKekulizeException &e) { + std::cerr << e.what() << std::endl; + } + }",Should this be boost logged? +1062,"@@ -57,9 +57,10 @@ def find_notifiers(notifier_name): + # pylint: enable=inconsistent-return-statements + + +-def convert_to_timestamp(violations): ++def convert_to_timestamp(session, violations): + """"""Convert violation created_at_datetime to timestamp string. + Args: ++ session (object): session object to work on. + violations (sqlalchemy_object): List of violations as sqlalchemy + row/record object with created_at_datetime. + Returns:",What is the reason for doing expunge here? This method is purely for converting the timestamp. +1063,"@@ -86,9 +86,15 @@ class TypeToSchema extends TypeUtil.SchemaVisitor { + List fields = Lists.newArrayListWithExpectedSize(fieldSchemas.size()); + for (int i = 0; i < structFields.size(); i += 1) { + Types.NestedField structField = structFields.get(i); ++ String origFieldName = structField.name(); ++ boolean isValid = validAvroName(origFieldName); ++ String fieldName = isValid ? origFieldName : sanitize(origFieldName); + Schema.Field field = new Schema.Field( +- structField.name(), fieldSchemas.get(i), null, ++ sanitize(fieldName), fieldSchemas.get(i), null, + structField.isOptional() ? JsonProperties.NULL_VALUE : null); ++ if (!isValid) { ++ field.addProp(AvroSchemaUtil.ORIGINAL_FIELD_NAME_PROP, origFieldName); ++ } + field.addProp(AvroSchemaUtil.FIELD_ID_PROP, structField.fieldId()); + fields.add(field); + }",This calls sanitize twice if the name isn't valid. +1064,"@@ -0,0 +1,13 @@ ++class Proposal < ActiveRecord::Base ++ has_one :cart ++ ++ validates :flow, presence: true, inclusion: {in: ApprovalGroup::FLOWS} ++ validates :status, presence: true, inclusion: {in: Approval::STATUSES} ++ ++ after_initialize :set_default_flow ++ ++ ++ def set_default_flow ++ self.flow ||= 'parallel' ++ end ++end",Is there an equivalent that'd allow zero or one? +1065,"@@ -234,6 +234,13 @@ func (m *taskExecutor) repeatWith() (err error) { + m.resetK8sClient(resource) + } + ++ if rwExec.isTaskObjectNameRepeat() { ++ // if repetition is based on task object name itself, then the task's ++ // object name needs to be set ++ m.metaTaskExec.setObjectName(resource) ++ m.objectName = resource ++ } ++ + // set the currently active repeat resource + util.SetNestedField(m.templateValues, resource, string(v1alpha1.ListItemsTLP), string(v1alpha1.CurrentRepeatResourceLITP)) + ",Is it possible to update/re-evaluate entire metatask object for every repeat? If we decide/need to use a repeatWith resources in let us say labelSelector(bad example) then we would have to add another logic to update those properties. +1066,"@@ -47,7 +47,7 @@ func accountImport(args []string) string { + } + wallet := cfg.Wallet + fmt.Printf(""#%s: Enter your private key, which will not be exposed on the screen.\n"", name) +- privateKeyBytes, err := terminal.ReadPassword(syscall.Stdin) ++ privateKeyBytes, err := terminal.ReadPassword(int(syscall.Stdin)) + if err != nil { + log.L().Error(""fail to get private key"", zap.Error(err)) + return err.Error()",unnecessary conversion (from `unconvert`) +1067,"@@ -30,7 +30,6 @@ int main (int argc, char *argv[]) + int universe_size; + char *kvsname; + char *val; +- char pmi_fd[16]; + char pmi_rank[16]; + char pmi_size[16]; + int result;",typo in commit message `openening` +1068,"@@ -10,7 +10,10 @@ + + #include + +-#include ++#define ADIOS_HAVE_PHDF5 // so hdf5 related items are loaded in ADIOS_CPP.h ++//#include ""ADIOS_CPP.h"" ++#include ""adios2.h"" ++#include ""adios2/engine/hdf5/HDF5ReaderP.h"" + + int main(int argc, char *argv[]) + {",User-code doesn't see the internal ADIOS headers anymore. This whole include block should just be `#include ` +1069,"@@ -20,7 +20,8 @@ class BucketViewTest(BaseWebTest, unittest.TestCase): + + def test_buckets_are_global_to_every_users(self): + self.app.patch_json(self.record_url, +- {'permissions': {'read': [Authenticated]}}, ++ {'data': {}, ++ 'permissions': {'read': [Authenticated]}}, + headers=self.headers) + self.app.get(self.record_url, headers=get_user_headers('alice')) + ",nit: I guess we can omit this (unless you had a reason to specify it) +1070,"@@ -74,6 +74,11 @@ func (c *client) isSolicitedLeafNode() bool { + return c.kind == LEAF && c.leaf.remote != nil + } + ++// Returns true if this is a solicited leafnode and is not configured to be treated as a hub. ++func (c *client) isSpokeLeafNode() bool { ++ return c.kind == LEAF && c.leaf.remote != nil && !c.leaf.remote.Hub ++} ++ + func (c *client) isUnsolicitedLeafNode() bool { + return c.kind == LEAF && c.leaf.remote == nil + }",Why is Hub public? +1071,"@@ -114,7 +114,6 @@ func (agent *ecsAgent) capabilities() ([]*ecs.Attribute, error) { + } + + capabilities = agent.appendTaskENICapabilities(capabilities) +- capabilities = agent.appendENITrunkingCapabilities(capabilities) + + capabilities = agent.appendDockerDependentCapabilities(capabilities, supportedVersions) + ",why is this deleted? +1072,"@@ -1,5 +1,6 @@ +
    ""> +
    ""> ++

    Hey, before you start this...Have you done the Intro to Rails tutorial?

    +
    + <%= trail.topic.name %> +

    <%= link_to trail.name, trail %>

    ",Maybe move that into a partial +1073,"@@ -158,10 +158,13 @@ func TestBlockDAO(t *testing.T) { + require := require.New(t) + + ctx := context.Background() +- dao := NewBlockDAO(kvstore, indexer, false, config.Default.DB) ++ testDBFile, _ := ioutil.TempFile(os.TempDir(), ""db"") ++ cfg := config.Default.DB ++ cfg.DbPath = testDBFile.Name() ++ dao := NewBlockDAO(kvstore, indexer, false, cfg) + require.NoError(dao.Start(ctx)) + defer func() { +- require.NoError(dao.Stop(ctx)) ++ dao.Stop(ctx) + }() + + // receipts for the 3 blocks",Error return value of `dao.Stop` is not checked (from `errcheck`) +1074,"@@ -172,7 +172,7 @@ func handleMainConfigArgs(cmd *cobra.Command, args []string, app *ddevapp.DdevAp + if docrootRelPath != """" { + app.Docroot = docrootRelPath + if _, err = os.Stat(docrootRelPath); os.IsNotExist(err) { +- util.Failed(""The docroot provided (%v) does not exist"", docrootRelPath) ++ output.UserOut.Warnf(""Warning: the provided docroot at %s does not currently exist."", docrootRelPath) + } + } else if !cmd.Flags().Changed(""docroot"") { + app.Docroot = ddevapp.DiscoverDefaultDocroot(app)",util.Warning()? Easier to say. +1075,"@@ -38,6 +38,14 @@ func Trie(tx ethdb.Tx, slowChecks bool, quit <-chan struct{}) { + if errc != nil { + panic(errc) + } ++ select { ++ default: ++ case <-quit: ++ return ++ case <-logEvery.C: ++ log.Info(""trie account integrity"", ""key"", fmt.Sprintf(""%x"", k)) ++ } ++ + hasState, hasBranch, hasHash, hashes, _ := trie.UnmarshalTrieNode(v) + AssertSubset(k, hasBranch, hasState) + AssertSubset(k, hasHash, hasState)",this default is kinda superfluous (although i see it was already there before PR ) +1076,"@@ -53,11 +53,7 @@ public class NodeList implements List, Iterable, HasParent + private List observers = new ArrayList<>(); + + public NodeList() { +- this((Node) null); +- } +- +- public NodeList(Node parent) { +- setParentNode(parent); ++ parentNode = null; + } + + public NodeList(Collection n) {",How is this related? +1077,"@@ -3,6 +3,7 @@ class SubscriptionsController < ApplicationController + + def new + @plans = IndividualPlan.featured.active.ordered ++ @team_plans = TeamPlan.featured.ordered + end + + def edit","I'm breaking one of the rules here, it feels like the right thing to do. Open to alternative suggestions." +1078,"@@ -1,8 +1,8 @@ + shared_examples_for 'disables OpenSSH roaming' do + let(:disable_ssh_roaming) { %(echo -e ""Host *\n UseRoaming no\n"" | cat - $HOME/.ssh/config > $HOME/.ssh/config.tmp && mv $HOME/.ssh/config.tmp $HOME/.ssh/config) } +- let(:sexp) { sexp_find(subject, [:if, ""$(sw_vers -productVersion | cut -d . -f 2) -lt 12""]) } ++ let(:sexp) { sexp_find(subject, [:if, %(""$(sw_vers -productVersion 2>/dev/null | cut -d . -f 2)"" -lt 12)]) } + + it 'disables OpenSSH roaming' do +- sexp.should include_sexp [:cmd, disable_ssh_roaming] ++ expect(sexp).to include_sexp [:cmd, disable_ssh_roaming] + end + end","The use of `#should` was triggering an rspec depracation warning for me, which is why I switched this to the rspec 3 style." +1079,"@@ -172,7 +172,7 @@ bool ReaderProxy::requested_changes_set(std::vector& seqNumSet + { + auto chit = m_changesForReader.find(ChangeForReader_t(*sit)); + +- if(chit != m_changesForReader.end() && chit->isValid()) ++ if(chit != m_changesForReader.end()) + { + ChangeForReader_t newch(*chit); + newch.setStatus(REQUESTED);",Why are you setting the CacheChange as REQUESTED when it is not valid (it was erased from history)? +1080,"@@ -44,9 +44,12 @@ import { + isDataZeroForReporting, + } from '../util'; + +-const { __ } = wp.i18n; +-const { Component, Fragment } = wp.element; +-const { isEmpty } = lodash; ++/** ++ * WordPress dependencies ++ */ ++import { __ } from '@wordpress/i18n'; ++import { Component, Fragment } from '@wordpress/element'; ++import { isEmpty } from 'lodash'; + + class AnalyticsDashboardWidgetTopLevel extends Component { + constructor( props ) {",`lodash` shouldn't be grouped under WordPress dependencies +1081,"@@ -69,7 +69,7 @@ class GenericDataFile + /** + * Used by Avro reflection to instantiate this class when reading manifest files. + */ +- public GenericDataFile(org.apache.avro.Schema avroSchema) { ++ GenericDataFile(org.apache.avro.Schema avroSchema) { + this.avroSchema = avroSchema; + + Types.StructType schema = AvroSchemaUtil.convert(avroSchema).asNestedType().asStructType();",This needs to be public so that Avro can call it. +1082,"@@ -18,18 +18,7 @@ + /** + * External dependencies + */ +-import data, { TYPE_CORE } from 'GoogleComponents/data'; +-import SvgIcon from 'GoogleUtil/svg-icon'; +- +-export * from './storage'; +- +-const { apiFetch } = wp; +-const { +- addFilter, +- applyFilters, +-} = wp.hooks; +- +-const { ++import { + map, + isNull, + isUndefined,",`Google*` shouldn't be under External dependencies - seems like ESlint is not properly recognizing that these are aliases to internal dependencies. +1083,"@@ -245,6 +245,13 @@ class DataFrame(_Frame): + else: + super(DataFrame, self).__init__(_InternalFrame( + data, data_columns=index.data_columns, index_map=index.index_map)) ++ elif isinstance(data, ks.Series): ++ assert index is None ++ assert columns is None ++ assert dtype is None ++ assert not copy ++ data = data.to_dataframe() ++ super(DataFrame, self).__init__(data._internal) + else: + if isinstance(data, pd.DataFrame): + assert index is None",I think he meant the docstring in this constructor. yea we should fix +1084,"@@ -150,7 +150,18 @@ public abstract class BinaryDictionary implements Dictionary { + throw new IllegalStateException(""unknown resource scheme "" + resourceScheme); + } + } +- ++ ++ public static InputStream getResource(ResourceScheme scheme, String path) throws IOException { ++ switch(scheme) { ++ case CLASSPATH: ++ return getClassResource(path); ++ case FILE: ++ return Files.newInputStream(Paths.get(path)); ++ default: ++ throw new IllegalStateException(""unknown resource scheme "" + scheme); ++ } ++ } ++ + // util, reused by ConnectionCosts and CharacterDefinition + public static InputStream getClassResource(Class clazz, String suffix) throws IOException { + final InputStream is = clazz.getResourceAsStream(clazz.getSimpleName() + suffix);","so .. this basically follows the pattern from JapaneseTokenizer, I think. .. but somehow I don't see where we defined ResourceScheme? We're not referencing the one in kuromoji, right?" +1085,"@@ -525,8 +525,11 @@ namespace SkylineNightly + + private void DownloadSkylineTester(string skylineTesterZip, RunMode mode) + { +- // Make sure we can negotiate with HTTPS servers that demand TLS 1.2 (default in dotNet 4.6, but has to be turned on in 4.5) +- ServicePointManager.SecurityProtocol |= (SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12); ++ // The current recommendation from MSFT for future-proofing HTTPS https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls ++ // is don't specify TLS levels at all, let the OS decide. But we worry that this will mess up Win7 and Win8 installs, so we continue to specify explicitly ++ var Tls13 = (SecurityProtocolType)12288; // From decompiled SecurityProtocolType - compiler has no definition for some reason ++ ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | Tls13; ++ + using (var client = new WebClient()) + { + client.Credentials = new NetworkCredential(TEAM_CITY_USER_NAME, TEAM_CITY_USER_PASSWORD);",It would probably be better to do: const SecurityProtocolType Tls13 = (SecurityProtocolType)12288 +1086,"@@ -70,16 +70,6 @@ export default [ + updated_by: 1, + value: '' + }, +- { +- id: 12, +- key: 'labs', +- value: '{""subscribers"":true}', +- type: 'blog', +- created_at: '2015-01-12T18:29:01.000Z', +- created_by: 1, +- updated_at: '2015-10-27T17:39:58.288Z', +- updated_by: 1 +- }, + { + id: 13, + created_at: '2015-09-11T09:44:30.810Z',","Similar to the above, put this setting back but keep the value as `'{}'`" +1087,"@@ -130,7 +130,7 @@ def refresh_listen_count_aggregate(): + Assuming today is 2022-01-01 and this function is called for year_offset 1 and + year_count 1 then all of 2021 will be refreshed. + """""" +- ++ logger.info(""Starting to refresh continuous aggregates:"") + timescale.init_db_connection(config.SQLALCHEMY_TIMESCALE_URI) + + end_ts = int(datetime.now().timestamp()) - SECONDS_IN_A_YEAR","As discussed in chat - we should run this function within an app context which means that we'd already have a logger configured, and a connection to timescale set up" +1088,"@@ -33,12 +33,4 @@ + +- +- ++
    ",I'm curious about why this needed to be removed. +1089,"@@ -17,10 +17,10 @@ from scapy.config import conf + from scapy.base_classes import BasePacket,BasePacketList + from scapy.utils import do_graph,hexdump,make_table,make_lined_table,make_tex_table,get_temp_file + +-from scapy.consts import plt, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS ++from scapy.extlib import plt, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS + from functools import reduce + import scapy.modules.six as six +-from scapy.modules.six.moves import filter, range, zip ++from scapy.modules.six.moves import range, zip + + + #############",why did you remove `zip`? It is used! +1090,"@@ -90,7 +90,7 @@ func (bs *BrokerStatus) MarkTopicUnknown(reason, format string, args ...interfac + brokerCondSet.Manage(bs).MarkUnknown(BrokerConditionTopic, reason, format, args...) + } + +-func (bs *BrokerStatus) MarkTopicReady() { ++func (bs *BrokerStatus) MarkTopicReady(_ string) { + brokerCondSet.Manage(bs).MarkTrue(BrokerConditionTopic) + } + ",Is there any reason that we don't add a similar condition like `ChannelConditionTopic` to the channel? +1091,"@@ -1,4 +1,4 @@ +-children() + ->scalarNode('db_driver')->isRequired()->end() + ->scalarNode('default_context')->isRequired()->end() ++ ->scalarNode('category_manager') ++ ->info('if sonata-project/classification exists will set ""sonata.classification.manager.category"" | if you want to define your own category manager you need to implement \Sonata\MediaBundle\Model\CategoryManagerInterface and set the service name here') ++ ->defaultValue(null) ++ ->end() ++ ->scalarNode('force_disable_category') ++ ->info('true IF you really want to disable the relation with category') ++ ->defaultValue(false) ++ ->end() + ->end() + ; + ","Please add line breaks, so the line doesn't exceed 80 chars." +1096,"@@ -29,11 +29,10 @@ namespace OpenTelemetry.Instrumentation.AspNetCore + /// + /// Initializes a new instance of the class. + /// +- /// ActivitySource adapter instance. + /// Configuration options for ASP.NET Core instrumentation. +- public AspNetCoreInstrumentation(ActivitySourceAdapter activitySource, AspNetCoreInstrumentationOptions options) ++ public AspNetCoreInstrumentation(AspNetCoreInstrumentationOptions options) + { +- this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpInListener(""Microsoft.AspNetCore"", options, activitySource), null); ++ this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpInListener(""Microsoft.AspNetCore"", options), null); + this.diagnosticSourceSubscriber.Subscribe(); + } + ",I initially thought (inccoreclty) this is a breaking change! The public api analyzer is a gift! +1097,"@@ -243,7 +243,7 @@ _ostree_delta_compute_similar_objects (OstreeRepo *repo, + { + gboolean ret = FALSE; + g_autoptr(GHashTable) ret_modified_regfile_content = +- g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_ptr_array_unref); ++ g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + g_autoptr(GPtrArray) from_sizes = NULL; + g_autoptr(GPtrArray) to_sizes = NULL; + guint i, j;",I'm not sure how this one didn't segfault before. +1098,"@@ -27,6 +27,13 @@ import ( + ) + + var _ = Describe(""Endpoints"", func() { ++ const ( ++ ProtoUDP = 17 ++ ProtoIPIP = 4 ++ VXLANPort = 0 ++ VXLANVNI = 0 ++ ) ++ + for _, trueOrFalse := range []bool{true, false} { + kubeIPVSEnabled := trueOrFalse + var rrConfigNormalMangleReturn = Config{",Same points as in other test file. +1099,"@@ -16,14 +16,7 @@ + */ + package org.apache.lucene.analysis.hunspell; + +-import java.io.BufferedInputStream; +-import java.io.BufferedOutputStream; +-import java.io.BufferedReader; +-import java.io.IOException; +-import java.io.InputStream; +-import java.io.InputStreamReader; +-import java.io.LineNumberReader; +-import java.io.OutputStream; ++import java.io.*; + import java.nio.charset.Charset; + import java.nio.charset.CharsetDecoder; + import java.nio.charset.CodingErrorAction;","Did you run gradlew tidy? Wildcard imports shouldn't be there, hence the question." +1100,"@@ -4,7 +4,11 @@ describe TrailWithProgress do + it ""decorates its component"" do + user = double(""user"") + trail = build_stubbed(:trail) +- trail_with_progress = TrailWithProgress.new(trail, user: user) ++ trail_with_progress = TrailWithProgress.new( ++ trail, ++ user: user, ++ status_finder: double(StatusFinder), ++ ) + + expect(trail_with_progress).to be_a(SimpleDelegator) + expect(trail_with_progress.name).to eq(trail.name)",Put a comma after the last parameter of a multiline method call. +1101,"@@ -183,6 +183,11 @@ fpga_result errors_filter(fpga_properties *filter, int argc, char *argv[]) + FPGA_ACCELERATOR); + ON_FPGAINFO_ERR_GOTO( + res, out, ""setting type to FPGA_ACCELERATOR""); ++ ++ res = fpgaPropertiesSetInterface(*filter, ++ FPGA_IFC_DFL); ++ ON_FPGAINFO_ERR_GOTO( ++ res, out, ""setting type to FPGA_IFC_DFL""); + break; + case VERB_ALL: + default:",Is this going to restrict the output to *ONLY* ports that are bound to vfio-pci? That's not what we discussed yesterday. +1102,"@@ -18,6 +18,13 @@ var _ specsruntime.Syscalls = (*syscalls)(nil) + + // VerifySignature implements Syscalls. + func (sys syscalls) VerifySignature(signature specscrypto.Signature, signer address.Address, plaintext []byte) error { ++ // Dragons: this lets all id addresses off the hook -- we need to remove this ++ // once market actor code actually checks proposal signature. Depending on how ++ // that works we may want to do id address to pubkey address lookup here or we ++ // might defer that to VM ++ if signer.Protocol() == address.ID { ++ return nil ++ } + return crypto.ValidateSignature(plaintext, signer, signature) + } + ","Intention is to do the lookup here, I believe (where we can cache it). This would make the call non-pure function though. I'll confirm with lotus. ID addresses are the *only* addresses I expect to actually see here." +1103,"@@ -5,7 +5,7 @@ + Purpose + + Shows how to run an EMRFS command as a job step on an Amazon EMR cluster. This +-can be used to automate ERMFS commands and is an alternative to connecting through ++can be used to automate EMRFS commands and is an alternative to connecting through + SSH to run the commands manually. + """""" + ",electronic medical record file system (EMRFS) +1104,"@@ -438,6 +438,7 @@ var directives = []string{ + ""mailout"", // github.com/SchumacherFM/mailout + ""awslambda"", // github.com/coopernurse/caddy-awslambda + ""filter"", // github.com/echocat/caddy-filter ++ ""maxrequestbody"", + } + + const (","Put this higher in the list, like after ""bind"", since I guess we're considering the max request body size to be kind of a native/fundamental feature, built directly into the vhosts." +1105,"@@ -37,13 +37,11 @@ import ( + ) + + var ( +- ErrInvalidOrderType = status.Errorf(codes.InvalidArgument, ""invalid order type"") +- ErrAskNotFound = status.Errorf(codes.NotFound, ""ask not found"") +- ErrDeviceNotFound = status.Errorf(codes.NotFound, ""device not found"") +- ErrMinerNotFound = status.Errorf(codes.NotFound, ""miner not found"") +- errDealNotFound = status.Errorf(codes.NotFound, ""deal not found"") +- errTaskNotFound = status.Errorf(codes.NotFound, ""task not found"") +- errImageForbidden = status.Errorf(codes.PermissionDenied, ""specified image is forbidden to run"") ++ ErrDeviceNotFound = status.Errorf(codes.NotFound, ""device not found"") ++ ErrMinerNotFound = status.Errorf(codes.NotFound, ""miner not found"") ++ errDealNotFound = status.Errorf(codes.NotFound, ""deal not found"") ++ errTaskNotFound = status.Errorf(codes.NotFound, ""task not found"") ++ errImageForbidden = status.Errorf(codes.PermissionDenied, ""specified image is forbidden to run"") + + hubAPIPrefix = ""/sonm.Hub/"" + ",oh come on :( +1106,"@@ -76,7 +76,7 @@ public class ProtocolHandshake { + + if (result.isPresent()) { + Result toReturn = result.get(); +- LOG.info(String.format(""Detected dialect: %s"", toReturn.dialect)); ++ LOG.finest(String.format(""Detected dialect: %s"", toReturn.dialect)); + return toReturn; + } + }",This is an incorrect change. The dialect spoken is an important part of the handshake and should be communicated to users. +1107,"@@ -30,6 +30,7 @@ def get_gcloud_info(): + str: GCP project id + str: GCP Authenticated user + bool: Whether or not the installer is running in cloudshell ++ bool: Whether or not authenticated user is a service account + """""" + return_code, out, err = utils.run_command( + ['gcloud', 'info', '--format=json'])",Remove as this is not needed anymore. +1108,"@@ -10,3 +10,11 @@ class Interface: + class DoNothing: pass + + class DoNothing2: pass ++ ++class DoSomething: ++ def __init__(self, a_string: str, optional_int: int = None): ++ self.my_string = a_string ++ self.my_int = optional_int ++ ++ def do_it(self, new_int: int) -> int: ++ return self.my_int + new_int",This new class is for checking that #4551 works correctly with PlantUML output too. +1109,"@@ -168,6 +168,11 @@ func (c *controller) buildCertificates(ctx context.Context, ing *networkingv1bet + Kind: issuerKind, + Group: issuerGroup, + }, ++ Usages: []cmapi.KeyUsage{ ++ cmapi.UsageDigitalSignature, ++ cmapi.UsageKeyEncipherment, ++ cmapi.UsageServerAuth, // default for web facing certificates as per https://support.apple.com/en-us/HT210176 ++ }, + }, + } + ",Will this cause all certificates to be re-issued? +1110,"@@ -215,6 +215,10 @@ fpga_result enum_max10_metrics_info(struct _fpga_handle *_handle, + } + metric_name[strlen(metric_name)-1] = '\0'; + ++ if (tmp) { ++ free(tmp); ++ } ++ + // Metrics typw + result = read_sensor_sysfs_file(pglob.gl_pathv[i], SENSOR_SYSFS_TYPE, (void **)&tmp, &tot_bytes); + if (FPGA_OK != result) {",I think tmp is also leaked at the end of this loop if no error cases are encountered. +1111,"@@ -165,13 +165,14 @@ class BuildAvroProjection extends AvroCustomOrderSchemaVisitorspace(); + // Check from the cache, if space not exists, schemas also not exist +- auto status = ectx()->schemaManager()->checkSpaceExist(spaceName); +- if (!status.ok()) { ++ auto spaceId = ectx()->schemaManager()->toGraphSpaceID(spaceName); ++ if (spaceId < 0) { + DCHECK(onError_); + onError_(Status::Error(""Space not found for `%s'"", spaceName.c_str())); + return; + } + +- auto spaceId = ectx()->schemaManager()->toGraphSpaceID(spaceName); + session->setSpace(*sentence_->space(), spaceId); + FLOG_INFO(""Graph space switched to `%s', space id: %d"", sentence_->space()->c_str(), spaceId); + ","Why not use StatusOr ? We can't ensure spaceId is greater than zero, especially when AdHocSchemaManager is used." +1113,"@@ -17,11 +17,15 @@ import ( + ""context"" + ""encoding/json"" + ""fmt"" ++ ""io"" + ""os"" + ""strings"" ++ ""time"" + + ""github.com/shirou/gopsutil/process"" + ++ jrpc ""github.com/ethereum/go-ethereum/rpc"" ++ + ""github.com/chaos-mesh/chaos-mesh/api/v1alpha1"" + ""github.com/chaos-mesh/chaos-mesh/pkg/bpm"" + pb ""github.com/chaos-mesh/chaos-mesh/pkg/chaosdaemon/pb""",Does it seem we only use that as the json-rpc client? Do we have any other choice? It's a little weird. +1114,"@@ -68,12 +68,13 @@ class ControlField(Field): + or (role in (controlTypes.ROLE_TABLE, controlTypes.ROLE_TABLECELL, controlTypes.ROLE_TABLEROWHEADER, controlTypes.ROLE_TABLECOLUMNHEADER) and not formatConfig[""reportTables""]) + or (role in (controlTypes.ROLE_LIST, controlTypes.ROLE_LISTITEM) and controlTypes.STATE_READONLY in states and not formatConfig[""reportLists""]) + or (role in (controlTypes.ROLE_FRAME, controlTypes.ROLE_INTERNALFRAME) and not formatConfig[""reportFrames""]) ++ or (role in (controlTypes.ROLE_DELETED_CONTENT,controlTypes.ROLE_INSERTED_CONTENT) and not formatConfig[""reportRevisions""]) + ): + # This is just layout as far as the user is concerned. + return self.PRESCAT_LAYOUT + + if ( +- role in (controlTypes.ROLE_LINK, controlTypes.ROLE_HEADING, controlTypes.ROLE_BUTTON, controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKBOX, controlTypes.ROLE_GRAPHIC, controlTypes.ROLE_CHART, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TAB, controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_SLIDER, controlTypes.ROLE_SPINBUTTON, controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_PROGRESSBAR, controlTypes.ROLE_TOGGLEBUTTON, controlTypes.ROLE_MENUBUTTON, controlTypes.ROLE_TREEVIEW, controlTypes.ROLE_CHECKMENUITEM, controlTypes.ROLE_RADIOMENUITEM) ++ role in (controlTypes.ROLE_DELETED_CONTENT,controlTypes.ROLE_INSERTED_CONTENT,controlTypes.ROLE_LINK, controlTypes.ROLE_HEADING, controlTypes.ROLE_BUTTON, controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKBOX, controlTypes.ROLE_GRAPHIC, controlTypes.ROLE_CHART, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TAB, controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_SLIDER, controlTypes.ROLE_SPINBUTTON, controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_PROGRESSBAR, controlTypes.ROLE_TOGGLEBUTTON, controlTypes.ROLE_MENUBUTTON, controlTypes.ROLE_TREEVIEW, controlTypes.ROLE_CHECKMENUITEM, controlTypes.ROLE_RADIOMENUITEM) + or (role == controlTypes.ROLE_EDITABLETEXT and controlTypes.STATE_MULTILINE not in states and (controlTypes.STATE_READONLY not in states or controlTypes.STATE_FOCUSABLE in states)) + or (role == controlTypes.ROLE_LIST and controlTypes.STATE_READONLY not in states) + ):",Could you split this into multiple lines? +1115,"@@ -19,14 +19,11 @@ + + package org.apache.iceberg; + +-import java.util.Collection; + import java.util.List; + import java.util.Set; +-import org.apache.iceberg.expressions.Expression; + import org.apache.iceberg.io.CloseableIterable; + import org.apache.iceberg.relocated.com.google.common.base.Preconditions; + import org.apache.iceberg.relocated.com.google.common.collect.FluentIterable; +-import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap; + import org.apache.iceberg.relocated.com.google.common.collect.Iterables; + import org.apache.iceberg.relocated.com.google.common.collect.Lists; + import org.apache.iceberg.relocated.com.google.common.collect.Sets;",Doesn't the snapshot ID start off as null? It seems like we don't need to set it here. +1116,"@@ -93,7 +93,7 @@ func (t *V4Trie) Get(cidr V4CIDR) interface{} { + } + + func (t *V4Trie) LookupPath(buffer []V4TrieEntry, cidr V4CIDR) []V4TrieEntry { +- return t.root.lookupPath(buffer, cidr) ++ return t.root.lookupPath(buffer[:0], cidr) + } + + // LPM does a longest prefix match on the trie","I wondered why `buffer` was passed into `LookupPath`. What is happening here? Is `buffer[:0]` equivalent to `[]V4TrieEntry{}`, and hence `buffer` isn't needed any more?" +1117,"@@ -173,7 +173,9 @@ func (c *Expected) validateMining(ctx context.Context, + parentWeight fbig.Int, + parentReceiptRoot cid.Cid) error { + +- powerTable := NewPowerTableView(c.state.StateView(parentStateRoot)) ++ stateView := c.state.StateView(parentStateRoot) ++ sigValidator := NewSignatureValidator(stateView) ++ powerTable := NewPowerTableView(stateView) + + for i := 0; i < ts.Len(); i++ { + blk := ts.At(i)",nit: Ideally we would would use this abstraction everywhere we need this translation. I believe it's needed in the mining worker and the storage and market connectors. +1118,"@@ -169,6 +169,13 @@ func (c *CStorPoolController) cStorPoolAddEventHandler(cStorPoolGot *apis.CStorP + glog.Infof(""Pool %v is online"", string(pool.PoolPrefix)+string(cStorPoolGot.GetUID())) + c.recorder.Event(cStorPoolGot, corev1.EventTypeNormal, string(common.AlreadyPresent), string(common.MessageResourceAlreadyPresent)) + common.SyncResources.IsImported = true ++ if GetHash(cStorPoolGot) == """" { ++ hash, err := common.CalculateHash(cStorPoolGot.Spec.Disks.DiskList) ++ if err != nil { ++ glog.Errorf(""Failed to update openebs.io/csp-disk-hash value: %v"", err) ++ } ++ UpdateHash(cStorPoolGot, hash) ++ } + return string(apis.CStorPoolStatusOnline), nil + } + glog.Infof(""Pool %v already present"", string(pool.PoolPrefix)+string(cStorPoolGot.GetUID()))",need to fix the error message here +1119,"@@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.Sarif + internal const string DEFAULT_POLICY_NAME = ""default""; + + public PropertyBagDictionary() : base() { } +- ++ //CA1026 not fixed + public PropertyBagDictionary( + PropertyBagDictionary initializer = null, + IEqualityComparer comparer = null)",Unsure of how to handle this one. +1120,"@@ -1268,7 +1268,9 @@ public class FlowRunner extends EventHandler implements Runnable { + + public void kill() { + synchronized (this.mainSyncObj) { +- if (isKilled()) { ++ if (isKilled() || this.flowFinished) { ++ this.logger.info( ++ ""Dropping Kill action as execution "" + this.execId + "" is already finished.""); + return; + } + this.logger.info(""Kill has been called on execution "" + this.execId);","Will this.flowFinished verify with every finished state stated in Status.isStatusFinished method? If so, no need to verify isKilled." +1121,"@@ -0,0 +1,11 @@ ++package common ++ ++// DefaultRetrySettings indicates what the ""default"" retry settings ++// are if it is not specified on an Activity or for any unset fields ++// if a policy is explicitly set on a Child Workflow ++type DefaultRetrySettings struct { ++ InitialIntervalInSeconds int32 ++ MaximumIntervalCoefficient float64 ++ BackoffCoefficient float64 ++ MaximumAttempts int32 ++}","replace ""Child Workflow"" with ""any workflow""" +1122,"@@ -426,7 +426,9 @@ footer { + {{html .Name}} + + +- {{- if .IsDir}} ++ {{- if .IsSymlink }} ++ symbolic link ++ {{- else if .IsDir}} + — + {{- else}} + {{.HumanSize}}","Instead of showing the words ""symbolic link"" under the ""Size"" column, how about we introduce new icons for symbolic link to file and symbolic link to directory?" +1123,"@@ -47,9 +47,10 @@ class DateRange implements FilterEncoder, FacetBuilder + * Parses the given date range from a GET parameter and returns a Solr + * date range filter. + * +- * @param string $rangeFilter The range filter query string from the query URL ++ * @param string $dateRange + * @param array $configuration Facet configuration + * @return string Lucene query language filter to be used for querying Solr ++ * @internal param string $rangeFilter The range filter query string from the query URL + */ + public function decodeFilter($dateRange, array $configuration = array()) + {",Please add back the description of the parameter +1124,"@@ -17,7 +17,7 @@ function GraphiteBrowser () { + var searchPanel = createSearchPanel(); + var completerPanel = createCompleterPanel(); + var treeRoot = treePanel.getRootNode(); +- ++ + this.trees = { + graphite: treeRoot.findChild('id', 'GraphiteTree'), + mygraphs: treeRoot.findChild('id', 'MyGraphsTree'),",Superfluous space inserted. +1125,"@@ -8,7 +8,9 @@ + * @returns {Object} + */ + dom.urlPropsFromAttribute = function urlPropsFromAttribute(node, attribute) { +- const value = node[attribute]; ++ const value = !node.ownerSVGElement ++ ? node[attribute] ++ : node.getAttribute(attribute); + if (!value) { + return undefined; + }","Didn't fix the problem. `href=""""` for SVG will still result in `undefined` getting returned by this function." +1126,"@@ -69,13 +69,13 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture) + json::Object{{ + {""location"", location}, + {""bearing_before"", 0}, +- {""bearing_after"", 58}, ++ {""bearing_after"", 238}, + {""type"", ""depart""}, + }}}, + {""intersections"", + json::Array{{json::Object{ + {{""location"", location}, +- {""bearings"", json::Array{{58}}}, ++ {""bearings"", json::Array{{238}}}, + {""entry"", json::Array{{json::True()}}}, + {""out"", 0}}}}}}}}}, + ",This seems like a strange change ... I wouldn't think that a change to access tags in the profiles would result in different bearings in this tests? +1127,"@@ -90,10 +90,10 @@ class AppModule(appModuleHandler.AppModule): + # Move the review cursor so others can't access its previous position. + self._oldReviewPos = api.getReviewPosition() + self._oldReviewObj = self._oldReviewPos.obj +- api.setNavigatorObject(eventHandler.lastQueuedFocusObject) ++ api.setNavigatorObject(eventHandler.lastQueuedFocusObject, isFocus=True) + + def event_appModule_loseFocus(self): + if not config.conf[""reviewCursor""][""followFocus""]: +- api.setReviewPosition(self._oldReviewPos) ++ api.setReviewPosition(self._oldReviewPos, isCaret=False) + del self._oldReviewPos, self._oldReviewObj + inputCore.manager._captureFunc = None","As isCaret is False by default, explicitly specifying isCaret=False here is not needed, and is perhaps a little confusing. I'd prefer that anywhere in the codebase that isCaret is only ever specified if it needs to be set to true. Mirroring that of isFocus for setNavigatorObject." +1128,"@@ -38,7 +38,7 @@ module Selenium + port + end + +- IGNORED_ERRORS = [Errno::EADDRNOTAVAIL] ++ IGNORED_ERRORS = [Errno::EADDRNOTAVAIL].freeze + IGNORED_ERRORS << Errno::EBADF if Platform.cygwin? + IGNORED_ERRORS.freeze + ",We can't freeze this and then add something to it in the next line. The `freeze` on line 43 is sufficient. If Rubocop flags this we need to exclude it. +1129,"@@ -368,5 +368,9 @@ func consolidateAutomationPolicies(aps []*caddytls.AutomationPolicy) []*caddytls + return len(aps[i].Subjects) > len(aps[j].Subjects) + }) + ++ for i := 0; i < len(aps); i++ { ++ sort.Strings(aps[i].Subjects) ++ } ++ + return aps + }",Why is this needed? +1130,"@@ -215,6 +215,9 @@ func RegisterRoutes(m *macaron.Macaron) { + }, reqToken()) + + // Repositories ++ m.Get(""/users/:username/repos"", repo.ListUserRepos) ++ m.Get(""/orgs/:org/repos"", repo.ListOrgRepos) ++ + m.Combo(""/user/repos"", reqToken()).Get(repo.ListMyRepos). + Post(bind(api.CreateRepoOption{}), repo.Create) + m.Post(""/org/:org/repos"", reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)",Why not put two other routes after this line (221)? +1131,"@@ -25,9 +25,10 @@ ExecutionEngine::~ExecutionEngine() { + + Status ExecutionEngine::init(std::shared_ptr ioExecutor) { + auto addrs = network::NetworkUtils::toHosts(FLAGS_meta_server_addrs); +- if (!addrs.ok()) { ++ if (!addrs.ok() || addrs.value().empty()) { + return addrs.status(); + } ++ + metaClient_ = std::make_unique(ioExecutor, std::move(addrs.value())); + metaClient_->init(); + ","If FLAGS_meta_server_addrs is not empty, in which case ""toHosts"" return empty array?" +1132,"@@ -216,6 +216,8 @@ void ResetFactory() + */ + Settings.I2C_clockSpeed = DEFAULT_I2C_CLOCK_SPEED; + ++ Settings.JSONBoolWithQuotes(DEFAULT_JSON_USE_QUOTES); ++ + #ifdef PLUGIN_DESCR + strcpy_P(Settings.Name, PSTR(PLUGIN_DESCR)); + #endif // ifdef PLUGIN_DESCR","There is a function to output a ""JSONBool"" string. That would be a good start for finding uses. But maybe just have a look at where we decide whether it is a numerical or not, thus wrapping quotes around its value. Then you have it all I guess." +1133,"@@ -90,8 +90,9 @@ class SampledPlot: + sampled = data._sdf.sample(fraction=float(self.fraction)) + return DataFrame(data._internal.copy(sdf=sampled)).to_pandas() + elif isinstance(data, Series): ++ scol = data._kdf._internal.data_scols[0] + sampled = data._kdf._sdf.sample(fraction=float(self.fraction)) +- return DataFrame(data._kdf._internal.copy(sdf=sampled)).to_pandas() ++ return DataFrame(data._kdf._internal.copy(sdf=sampled, scol=scol)).to_pandas() + else: + ValueError(""Only DataFrame and Series are supported for plotting."") + ","oops, it should be `data._scol` so that it respects the expression stored in Series. Let me fix it quick." +1134,"@@ -1,6 +1,7 @@ + <% administrator = Role.new(administrator: true, editor: true, commenter: true) %> + <% editor = Role.new(editor: true, commenter: true) %> + <% commenter = Role.new(commenter: true) %> ++<% administerable = @plan.administerable_by?(current_user) %> + +

    <%= _('Set plan visibility') %>

    +

    <%= _('Public or organisational visibility is intended for finished plans. You must answer at least %{percentage}%% of the questions to enable these options. Note: test plans are set to private visibility by default.') % { :percentage => Rails.application.config.default_plan_percentage_answered } %>

    ",Thanks for moving this up with the rest of the variables. Much tidier :) +1135,"@@ -38,6 +38,12 @@ import ( + // DefaultAccountantFailureCount defines how many times we're allowed to fail to reach accountant in a row before announcing the failure. + const DefaultAccountantFailureCount uint64 = 3 + ++// DefaultPaymentInfo represents the default payment info for the alpha release ++var DefaultPaymentInfo = dto.PaymentPerTime{ ++ Price: money.NewMoney(0.001, money.CurrencyMyst), ++ Duration: 1 * time.Minute, ++} ++ + // InvoiceFactoryCreator returns a payment engine factory. + func InvoiceFactoryCreator( + dialog communication.Dialog,",I think `Rate` is a more precise and concise term for `PaymentPerTime`. +1136,"@@ -213,7 +213,7 @@ namespace pwiz.Skyline.Util + { + // No leading + or - : is it because description starts with a label, or because + mode is implied? + var limit = input.IndexOfAny(new[] { '+', '-', ']' }); +- if (limit < 0) ++ if (limit < posNext) + { + return null; + }","I think this should maybe be: var limit = input.IndexOfAny(new[] { '+', '-', ']' }, **posNext**); You pretty much want to ignore any sign that is before the ""M"". But, if there is a sign somewhere before the M, and also after the M, you'd want to be able to find the sign after the M, right?" +1137,"@@ -263,7 +263,12 @@ class OrderController extends BaseFrontController + + /* check cart count */ + $this->checkCartNotEmpty(); +- ++ ++ /* check stock not empty */ ++ if(true === ConfigQuery::checkAvailableStock()) { ++ $this->checkStockNotEmpty(); ++ } ++ + /* check delivery address and module */ + $this->checkValidDelivery(); + ","if `checkStockNotEmpty` returns a reponse, you must return it or your script will continue its execution." +1138,"@@ -46,7 +46,7 @@ import ( + ""github.com/prometheus/common/version"" + ""golang.org/x/sync/errgroup"" + v1 ""k8s.io/api/core/v1"" +- ""k8s.io/klog/v2"" ++ klogv2 ""k8s.io/klog/v2"" + ) + + const (",Any specific reason for this change? klog should work correctly here. +1139,"@@ -243,6 +243,9 @@ class Storage(StorageBase): + VALUES (:object_id, :parent_id, + :collection_id, (:data)::JSONB, + from_epoch(:last_modified)) ++ ON CONFLICT (id, parent_id, collection_id) DO UPDATE ++ SET data = (:data)::JSONB, ++ last_modified = from_epoch(:last_modified) + RETURNING id, as_epoch(last_modified) AS last_modified; + """""" + placeholders = dict(object_id=record[id_field],",we don't mention `last_modified` here? +1140,"@@ -1,6 +1,10 @@ +-const html = require('yo-yo') + const ActionBrowseTagline = require('./ActionBrowseTagline') + const { localIcon } = require('./icons') ++const { h } = require('preact') ++const hyperx = require('hyperx') ++const html = hyperx(h) ++ ++let inputEl + + module.exports = (props) => { + const isHidden = Object.keys(props.files).length === 0",same deal about the global state maybe interfering as in ActionBrowseTagline +1141,"@@ -172,5 +172,17 @@ namespace Nethermind.Core.Test.Caching + + count.Should().Be(itemsToKeep); + } ++ ++ [Test] ++ public void Wrong_capacity_number_at_constructor() ++ { ++ int maxCapacity = 0; ++ ++ Assert.Throws(() => ++ { ++ LruCache cache = new LruCache(maxCapacity, ""test""); ++ }); ++ ++ } + } + }",so sweet to see a test as the first thing +1142,"@@ -161,6 +161,12 @@ struct flb_config *flb_config_init() + config->http_port = flb_strdup(FLB_CONFIG_HTTP_PORT); + #endif + ++ config->http_proxy = getenv(""HTTP_PROXY""); ++ if (strcmp(config->http_proxy, """")) { ++ /* Proxy should not be set when the `HTTP_PROXY` is set to """" */ ++ config->http_proxy = NULL; ++ } ++ + config->cio = NULL; + config->storage_path = NULL; + config->storage_input_plugin = NULL;","usually when HTTP_PROXY="""" (empty), proxy should be disabled. could you set it to NULL when it's empty string?" +1143,"@@ -62,6 +62,10 @@ class SimpleResizer implements ResizerInterface + if ($settings['height'] == null) { + $settings['height'] = (int) ($settings['width'] * $size->getHeight() / $size->getWidth()); + } ++ ++ if ($settings['width'] == null) { ++ $settings['width'] = (int) ($settings['height'] * $size->getWidth() / $size->getHeight()); ++ } + + return $this->computeBox($media, $settings); + }",Can you throw an exception if width or height are both null +1144,"@@ -26,8 +26,8 @@ import ( + ) + + var ( +- HTTPSchemeHTTP = HTTPSchemeKey.String(""http"") +- HTTPSchemeHTTPS = HTTPSchemeKey.String(""https"") ++ httpSchemeHTTP = HTTPSchemeKey.String(""http"") ++ httpSchemeHTTPS = HTTPSchemeKey.String(""https"") + ) + + // NetAttributesFromHTTPRequest generates attributes of the net",This is a breaking change. I guess these might have been intentionally exported. +1145,"@@ -225,6 +225,8 @@ abstract class BaseTableScan implements TableScan { + long splitSize; + if (options.containsKey(TableProperties.SPLIT_SIZE)) { + splitSize = Long.parseLong(options.get(TableProperties.SPLIT_SIZE)); ++ } else if (options.containsKey(TableProperties.METADATA_SPLIT_SIZE)) { ++ splitSize = Long.parseLong(options.get(TableProperties.METADATA_SPLIT_SIZE)); + } else { + splitSize = targetSplitSize(ops); + }","I don't think this is necessary. When options are used to set the split size in the Spark reader, it uses `TableProperties.SPLIT_SIZE` to pass it here. That should work for metadata tables as well, right? The situation that we need to handle in this PR is setting the default, like you had before. We just want to use a metadata split size so you can set it and not have the same split size used (by default) for both metadata and data scans." +1146,"@@ -267,6 +267,10 @@ const ( + Add Operator = '+' + // Subtract implements binary - (only works on integers) + Subtract = '-' ++ // Multiply implements multiplication between two types ++ Multiply = '×' ++ // Divide implements division, currently only between integers ++ Divide = '÷' + // Modulo implements % (including string interpolation) + Modulo = '%' + // LessThan implements <","wait a sec, shouldn't this be `'*'`?" +1147,"@@ -127,6 +127,9 @@ func (oi *OVFImporter) buildDaisyVars(bootDiskImageURI string, machineType strin + varMap[""boot_disk_image_uri""] = bootDiskImageURI + if oi.params.IsInstanceImport() { + varMap[""instance_name""] = oi.params.InstanceNames ++ if oi.params.ComputeServiceAccount != """" { ++ varMap[""compute_service_account""] = oi.params.ComputeServiceAccount ++ } + } else { + varMap[""machine_image_name""] = oi.params.MachineImageName + }",It think you'll want the var for GMI import as well: daisy_workflows/ovf_import/create_gmi.wf.json (Unfortunately there's duplication between the two :/ ) +1148,"@@ -21,6 +21,7 @@ from selenium.webdriver.remote.remote_connection import RemoteConnection + class FirefoxRemoteConnection(RemoteConnection): + def __init__(self, remote_server_addr, keep_alive=True): + RemoteConnection.__init__(self, remote_server_addr, keep_alive) ++ self._commands[""GET_CONTEXT""] = ('GET', '/session/$sessionId/moz/context') + + self._commands[""SET_CONTEXT""] = (""POST"", ""/session/$sessionId/moz/context"") + self._commands[""ELEMENT_GET_ANONYMOUS_CHILDREN""] = \",Nit: Group this with the other commands by moving it down one line. +1149,"@@ -512,6 +512,9 @@ public class VectorizedPageIterator extends BasePageIterator { + throw new ParquetDecodingException(""could not read page in col "" + desc, e); + } + } else { ++ if (dataEncoding != Encoding.PLAIN) { ++ throw new UnsupportedOperationException(""Unsupported encoding: "" + dataEncoding); ++ } + plainValuesReader = new ValuesAsBytesReader(); + plainValuesReader.initFromPage(valueCount, in); + dictionaryDecodeMode = DictionaryDecodeMode.NONE;","I would like to emphasize that a user can use non-vectorized reads to handle this file so maybe something like ""Cannot perform a vectorized read of ParquetV2 File with encoding %s, disable vectorized reading with $param to read this table/file""" +1150,"@@ -101,6 +101,10 @@ class RangeBase(luigi.WrapperTask): + now = luigi.IntParameter( + default=None, + description=""set to override current time. In seconds since epoch"") ++ param_name = luigi.Parameter( ++ default=None, ++ description=""parameter name used to pass in parameterized value. Defaults to None, meaning use first positional parameter"", ++ positional=False) + + @property + def of_cls(self):","Maybe add `positional=False`. It does not need it more than the other parameters, but one must start somewhere." +1151,"@@ -9,8 +9,8 @@ const expect = require('chai').expect, + MongoError = require('../../../lib/core/error').MongoError, + ReadPreference = require('../../../lib/core/topologies/read_preference'); + +-const rsWithPrimaryPath = f('%s/../spec/max-staleness/ReplicaSetWithPrimary', __dirname); +-const rsWithoutPrimaryPath = f('%s/../spec/max-staleness/ReplicaSetNoPrimary', __dirname); ++const rsWithPrimaryPath = f('%s/../../spec/max-staleness/ReplicaSetWithPrimary', __dirname); ++const rsWithoutPrimaryPath = f('%s/../../spec/max-staleness/ReplicaSetNoPrimary', __dirname); + + describe('Max Staleness', function() { + describe('ReplicaSet without primary', function() {","Since we're here, can we use a template?" +1152,"@@ -214,3 +214,10 @@ def postgres_db_info_resource(init_context): + dialect='postgres', + load_table=_do_load, + ) ++ ++ ++if __name__ == '__main__': ++ # This is a brutal hack. When the SparkSession is created for the first time there is a lengthy ++ # download process from Maven. This allows us to run python -m airline_demo.resources in the ++ # Dockerfile and avoid a long runtime delay before each containerized solid executes. ++ spark_session_local.resource_fn(None)",saw you're also doing this in `test_types.py`: `spark = _spark_context()['test'].resources['spark'].resource_fn(None)` since `_spark_context()` uses `spark_session_local` won't the above break the tests? +1153,"@@ -49,10 +49,10 @@ var _ = Context(""with initialized Felix, etcd datastore, 3 workloads"", func() { + defaultProfile := api.NewProfile() + defaultProfile.Name = ""default"" + defaultProfile.Spec.LabelsToApply = map[string]string{""default"": """"} +- defaultProfile.Spec.EgressRules = []api.Rule{{Action: ""allow""}} ++ defaultProfile.Spec.EgressRules = []api.Rule{{Action: api.Allow}} + defaultProfile.Spec.IngressRules = []api.Rule{{ +- Action: ""allow"", +- Source: api.EntityRule{Tag: ""default""}, ++ Action: api.Allow, ++ Source: api.EntityRule{Selector: ""default == ''""}, + }} + _, err := client.Profiles().Create(utils.Ctx, defaultProfile, utils.NoOptions) + Expect(err).NotTo(HaveOccurred())",`has(default)` i think is the preferred way of doing this +1154,"@@ -35,9 +35,11 @@ class ScalarSpaceEncoderTest(unittest.TestCase): + def testScalarSpaceEncoder(self): + """"""scalar space encoder"""""" + # use of forced=True is not recommended, but used in the example for readibility, see scalar.py +- sse = ScalarSpaceEncoder(1,1,2,False,2,1,1,None,0,False,""delta"", forced=True) ++ sse = ScalarSpaceEncoder(w=21,minval=1,maxval=2,n=100,radius=1, ++ resolution=1,name=""SP1"",verbosity=0,clipInput=False,space=""delta"") + self.assertTrue(sse.isDelta()) +- sse = ScalarSpaceEncoder(1,1,2,False,2,1,1,None,0,False,""absolute"", forced=True) ++ sse = ScalarSpaceEncoder(w=21,minval=1,maxval=2,n=100,radius=1, ++ resolution=1,name=""sp2"",verbosity=0,clipInput=False,space=""absolute"") + self.assertFalse(sse.isDelta()) + + ",always put a space after a comma +1155,"@@ -289,6 +289,10 @@ public class LFMainActivity extends SharedMediaActivity { + mediaAdapter.notifyItemChanged(toggleSelectPhoto(m)); + editMode = true; + } ++ else ++ { ++ selectAllPhotosUpToFav(getImagePosition(m.getPath())); ++ } + } else selectAllPhotosUpTo(getImagePosition(m.getPath()), mediaAdapter); + return true; + }","@angmas1 move the else up, next to the closing bracket of the if block. Also, there is no need for the braces as your else statement contains only a single line. Make your if-else block similar to the block in lines 277-280." +1156,"@@ -111,7 +111,7 @@ class WebDriver(object): + + def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', + desired_capabilities=None, browser_profile=None, proxy=None, +- keep_alive=False, file_detector=None): ++ keep_alive=False, file_detector=None, options=None): + """""" + Create a new driver that will issue commands using the wire protocol. + ",@AutomatedTester @davehunt thoughts on a new keyword argument? +1157,"@@ -44,7 +44,7 @@ public class NodeStatus { + public NodeStatus( + NodeId nodeId, + URI externalUri, +- int maxSessionCount, ++ Integer maxSessionCount, + Set slots, + Availability availability) { + this.nodeId = Require.nonNull(""Node id"", nodeId);",This change shouldn't be necessary for this PR. Please remove it. +1158,"@@ -27,7 +27,8 @@ import ( + ) + + func testAlertmanagerInstanceNamespacesAllNs(t *testing.T) { +- ctx := framework.NewTestCtx(t) ++ testCtx := framework.NewTestCtx(t) ++ ctx := &testCtx + defer ctx.Cleanup(t) + + // create 3 namespaces:","This variable is mostly unused, how about we make `NewTestCtx` return a pointer?" +1159,"@@ -7,6 +7,10 @@ import ( + ""k8s.io/klog/v2"" + ) + ++const ( ++ maxPayloadLen = 32 * 1 << 20 // 32Mi ++) ++ + type Reader struct { + reader io.Reader + }",What is the basis of this value? +1160,"@@ -28,6 +28,7 @@ + #include + #include + ++#include ""gce_metadata.h"" + #include ""stackdriver.h"" + #include ""stackdriver_conf.h"" + ",Nit: was this extra blank line added intentionally? +1161,"@@ -5837,6 +5837,12 @@ initialize_exception_record(EXCEPTION_RECORD* rec, app_pc exception_address, + case ILLEGAL_INSTRUCTION_EXCEPTION: + rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; ++ case GUARD_PAGE_EXCEPTION: ++ rec->ExceptionCode = STATUS_GUARD_PAGE_VIOLATION; ++ rec->NumberParameters = 2; ++ rec->ExceptionInformation[0]=EXCEPTION_EXECUTE_FAULT /* execution tried */; ++ rec->ExceptionInformation[1]=(ptr_uint_t)exception_address; ++ break; + default: + ASSERT_NOT_REACHED(); + }",nit: inconsistent spacing around = +1162,"@@ -12,7 +12,6 @@ + namespace Sonata\MediaBundle\Model; + + use Imagine\Image\Box; +-use Sonata\ClassificationBundle\Model\CategoryInterface; + use Symfony\Component\Validator\Context\ExecutionContextInterface; + use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface; + ",We still need this import +1163,"@@ -60,7 +60,7 @@ public class TestBinPackStrategy extends TableTestBase { + } + + @Override +- public Set rewriteFiles(String groupId, List filesToRewrite) { ++ public Set rewriteFiles(List filesToRewrite) { + throw new UnsupportedOperationException(); + } + }","We are pulling this because we removed ""groupID"" state and put it into the strategy implementations" +1164,"@@ -17,8 +17,7 @@ + #include + + #include ""gtest/gtest.h"" +-#define ONEAPI_DAL_DATA_PARALLEL +-#include ""oneapi/dal/algo/kmeans_init.hpp"" ++#include ""oneapi/dal/algo/kmeans_init/compute.hpp"" + #include ""oneapi/dal/table/homogen.hpp"" + #include ""oneapi/dal/table/row_accessor.hpp"" + ",Is this file actually related to PCA? +1165,"@@ -6,7 +6,7 @@ import createEnableTracking from './createEnableTracking'; + import createTrackEvent from './createTrackEvent'; + + const DEFAULT_CONFIG = { +- isFirstAdmin: false, ++ isOwner: false, + trackingEnabled: false, + trackingID: '', + referenceSiteURL: '',","See above, this should probably remain `isFirstAdmin`." +1166,"@@ -499,7 +499,7 @@ type ArrayExpression struct { + + Elements []Expression + +- typ MonoType ++ Type MonoType + } + + func (*ArrayExpression) NodeType() string { return ""ArrayExpression"" }",Why the change to make it public? The expression interface has the `TypeOf` method? +1167,"@@ -1562,7 +1562,7 @@ namespace NLog.UnitTests.Targets + } + + [Fact] +- public void Single_Archive_File_Rolls_Correctly() ++ public void SingleArchiveFileRollsCorrectly() + { + var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var tempFile = Path.Combine(tempPath, ""file.txt"");","don't mind the snake cases in the test names. If there are in the test cases, it's fine IMO" +1168,"@@ -28,6 +28,11 @@ type identityRegistrationDto struct { + Registered bool `json:""registered""` + } + ++type identityUnlockingDto struct { ++ Id string `json:""id""` ++ Passphrase string `json:""passphrase""` ++} ++ + type identitiesApi struct { + idm identity.IdentityManagerInterface + mysteriumClient server.Client",`Id` defines REST resource address and should not be in payload +1169,"@@ -20,8 +20,11 @@ def main(): + nargs='+', + default=[100, 300, 1000], + help='proposal numbers, only used for recall evaluation') ++ parser.add_argument( ++ '--class_wise', action='store_true', help='whether eval class wise ap') + args = parser.parse_args() +- coco_eval(args.result, args.types, args.ann, args.max_dets) ++ coco_eval(args.result, args.types, args.ann, args.max_dets, ++ args.class_wise) + + + if __name__ == '__main__':",We can omit the underscore and just use `classwise`. +1170,"@@ -77,10 +77,12 @@ class MediaAdminController extends Controller + $datagrid->setValue('context', null, $context); + + // retrieve the main category for the tree view +- $category = $this->container->get('sonata.classification.manager.category')->getRootCategory($context); ++ $rootCategory = $this->container->get('sonata.classification.manager.category')->getRootCategory($context); ++ // This should be safe as the root category has to exist for a given context but I do not like fatal errors ++ $rootCategoryId = !empty($rootCategory) ? $rootCategory->getId() : null; + + if (!$filters) { +- $datagrid->setValue('category', null, $category); ++ $datagrid->setValue('category', null, $rootCategoryId); + } + if ($request->get('category')) { + $categoryByContext = $this->container->get('sonata.classification.manager.category')->findOneBy(array(",Why not throw an exception instead then? +1171,"@@ -71,8 +71,7 @@ abstract class DataIterator implements CloseableIterator { + + InputFile getInputFile(FileScanTask task) { + Preconditions.checkArgument(!task.isDataTask(), ""Invalid task type""); +- +- return inputFiles.get(task.file().path().toString()); ++ return getInputFile(task.file().path().toString()); + } + + InputFile getInputFile(String location) {",Looks like this doesn't need to change. Can you revert this? +1172,"@@ -3,6 +3,7 @@ import sys + from cliquet.scripts import cliquet + from pyramid.scripts import pserve + from pyramid.paster import bootstrap ++from config import template + + CONFIG_FILE = 'config/kinto.ini' + ",please import it like `from kinto.config import template` +1173,"@@ -173,7 +173,7 @@ public final class Configuration { + } + + public boolean isIsolationFilterOpen(String microservice) { +- String p = getStringProperty(""false"", ++ String p = getStringProperty(""true"", + PROP_ROOT + microservice + ""."" + FILTER_ISOLATION + FILTER_OPEN, + PROP_ROOT + FILTER_ISOLATION + FILTER_OPEN); + return Boolean.parseBoolean(p);","There are lots of default value changed, not sure if it break the old behavior." +1174,"@@ -10,13 +10,15 @@ import ( + ""context"" + ""encoding/hex"" + ""math/big"" ++ ""net"" ++ ""strconv"" + +- ""github.com/golang/protobuf/jsonpb"" + ""github.com/golang/protobuf/proto"" +- peerstore ""github.com/libp2p/go-libp2p-peerstore"" + ""github.com/pkg/errors"" + ""github.com/prometheus/client_golang/prometheus"" + ""go.uber.org/zap"" ++ ""google.golang.org/grpc"" ++ ""google.golang.org/grpc/reflection"" + + ""github.com/iotexproject/iotex-core/action"" + ""github.com/iotexproject/iotex-core/actpool""",File is not `goimports`-ed (from `goimports`) +1175,"@@ -29,9 +29,9 @@ namespace Nethermind.Cli.Modules + public object[] Peers() => NodeManager.Post(""admin_peers"").Result; + + [CliFunction(""admin"", ""addPeer"")] +- public string AddPeer(string enode) => NodeManager.Post(""admin_addPeer"", enode).Result; ++ public string AddPeer(string enode, bool addToStaticNodes = false) => NodeManager.Post(""admin_addPeer"", enode, addToStaticNodes).Result; + + [CliFunction(""admin"", ""removePeer"")] +- public string RemovePeer(string enode) => NodeManager.Post(""admin_removePeer"", enode).Result; ++ public string RemovePeer(string enode, bool addToStaticNodes = false) => NodeManager.Post(""admin_removePeer"", enode, addToStaticNodes).Result; + } + }",parameter should be called removeFromStaticNodes +1176,"@@ -221,7 +221,9 @@ class RequestContext: + ServiceRequestHandler = Callable[[RequestContext, ServiceRequest], Optional[ServiceResponse]] + + +-def handler(operation: str = None, context: bool = True, expand: bool = True): ++def handler( ++ operation: str = None, context: bool = True, expand: bool = True, override: bool = False ++): + """""" + Decorator that indicates that the given function is a handler + """"""","The handler will have an extra property in the marker to signal the implementation is in the provider, for the cases we want to add functionality, for example, custom implementations not in moto." +1177,"@@ -14,6 +14,18 @@ class Subscription < ActiveRecord::Base + notifier.send_notifications + end + ++ def active? ++ deactivated_on.nil? ++ end ++ ++ def deactivate ++ update_column(:deactivated_on, Date.today) ++ end ++ ++ def activate ++ update_column(:deactivated_on, nil) ++ end ++ + private + + def self.subscriber_emails","Is this method actually being used anywhere? If not, I think we should remove it." +1178,"@@ -400,7 +400,7 @@ namespace AutoRest.Extensions + { + var bodyParameterType = bodyParameter.ModelType as CompositeType; + if (bodyParameterType != null && +- (bodyParameterType.ComposedProperties.Count(p => !p.IsConstant) <= Settings.Instance.PayloadFlatteningThreshold || ++ (bodyParameterType.ComposedProperties.Count(p => !p.IsConstant && !p.IsReadOnly) <= Settings.Instance.PayloadFlatteningThreshold || + bodyParameter.ShouldBeFlattened())) + { + var parameterTransformation = new ParameterTransformation",Thanks! I somehow lost this between my far too many branchs. +1179,"@@ -30,13 +30,14 @@ import socket + import sys + + from .firefox_binary import FirefoxBinary ++from .options import Options + from .remote_connection import FirefoxRemoteConnection + from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + from selenium.webdriver.firefox.extension_connection import ExtensionConnection + from selenium.webdriver.firefox.firefox_profile import FirefoxProfile + from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver + from .service import Service +-from .options import Options ++from .webelement import FirefoxWebElement + + + class WebDriver(RemoteWebDriver):",i think this should get put into its own file. This could start to grow :) +1180,"@@ -39,6 +39,13 @@ const ( + // variable containers' config, which will be used by the AWS SDK to fetch + // credentials. + awsSDKCredentialsRelativeURIPathEnvironmentVariableName = ""AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"" ++ // pauseContainerName is the internal name for the pause container ++ pauseContainerName = ""~internal~ecs~pause"" ++ // pauseContainerImage is container image used to create the pause container ++ // TODO: Modify this to amazon/amazon-ecs-pause or something similar ++ pauseContainerImage = ""gcr.io/google_containers/pause:latest"" ++ // networkModeNone specifies the string used to define the `none` docker networking mode ++ networkModeNone = ""none"" + ) + + // TaskOverrides are the overrides applied to a task",Can you add a TODO for loading the tarball of the pause image into Docker? +1181,"@@ -259,7 +259,6 @@ public class ProcessJob extends AbstractProcessJob { + } + throw new RuntimeException(e); + } finally { +- this.process = null; + info(""Process completed "" + + (success ? ""successfully"" : ""unsuccessfully"") + "" in "" + + ((System.currentTimeMillis() - startMs) / 1000) + "" seconds."");",Is there any value in setting the process to null like this? +1182,"@@ -35,6 +35,14 @@ void SoftmaxWithLossLayer::Reshape( + const vector*>& bottom, const vector*>& top) { + LossLayer::Reshape(bottom, top); + softmax_layer_->Reshape(softmax_bottom_vec_, softmax_top_vec_); ++ softmax_axis_ = this->layer_param_.softmax_param().axis(); ++ outer_num_ = bottom[0]->count(0, softmax_axis_); ++ inner_num_ = bottom[0]->count(softmax_axis_ + 1); ++ CHECK_EQ(outer_num_ * inner_num_, bottom[1]->count()) ++ << ""Number of labels must match number of predictions; "" ++ << ""e.g., if softmax axis == 1 and prediction shape is (N, C, H, W), "" ++ << ""label count (number of labels) must be N*H*W, "" ++ << ""with integer values in {0, 1, ..., C-1}.""; + if (top.size() >= 2) { + // softmax output + top[1]->ReshapeLike(*bottom[0]);",This could be a good time to add a check that the prediction and target dimensions (except channel) agree? +1183,"@@ -3920,6 +3920,11 @@ build_bb_ilist(dcontext_t *dcontext, build_bb_t *bb) + if (!bb_process_interrupt(dcontext, bb)) + break; + } ++#ifdef AARCH64 ++ /* OP_isb, when mangled, has a potential side exit. */ ++ else if (instr_get_opcode(bb->instr) == OP_isb) ++ break; ++#endif + #if 0/*i#1313, i#1314*/ + else if (instr_get_opcode(bb->instr) == OP_getsec) { + /* XXX i#1313: if we support CPL0 in the future we'll need to","The requirement that OP_isb is bb-final needs to be a rule for clients, just like the rule that syscalls and interrupts must be bb-final: i.e., please add it to the dr_register_bb_event() docs." +1184,"@@ -83,7 +83,7 @@ define([""userSettings""], function (userSettings) { + + if (html += '
    ', showControls) { + html += ''; +- html += (totalRecordCount ? startIndex + 1 : 0) + ""-"" + recordsEnd + "" of "" + totalRecordCount; ++ html += Globalize.translate(""ListPaging"").replace(""{0}"", (totalRecordCount ? startIndex + 1 : 0) + ""-"" + recordsEnd).replace(""{1}"", totalRecordCount); + html += """"; + } + ",The translate library has a method to replace the variables. +1185,"@@ -155,6 +155,18 @@ class SeriesTest(ReusedSQLTestCase, SQLTestUtils): + with self.assertRaisesRegex(TypeError, msg): + ds.isin(1) + ++ def test_fillna(self): ++ ps = pd.Series([np.nan, 2, 3, 4, np.nan, 6], name='x') ++ ks = koalas.from_pandas(ps) ++ ++ self.assert_eq(ks.fillna(0), ps.fillna(0)) ++ self.assert_eq(ks.fillna(0, inplace=True), ps.fillna(0, inplace=True)) ++ self.assert_eq(ks.fillna({'x': 0}), ps.fillna({'x': 0})) ++ ++ s_nan = pd.Series([0], index=['x'], dtype=int) ++ self.assert_eq(ks.fillna(s_nan), ++ ps.fillna(s_nan)) ++ + def test_dropna(self): + ps = pd.Series([np.nan, 2, 3, 4, np.nan, 6], name='x') + ","i don't think this test case is correct. in both cases inpalce=True returns nothing. We need to compare the ks. Also we probably need to make a copy of it. Otherwise you pollute the following ""ks"" because ks has been changed." +1186,"@@ -124,6 +124,7 @@ with outfile.open(""w"") as f, contextlib.redirect_stdout(f): + tls.TlsClienthelloHook, + tls.TlsStartClientHook, + tls.TlsStartServerHook, ++ tls.TlsHandshakeHook, + ] + ) + ","Any proposals how to make the naming somehow include the ""completed"" idea of this hook? `TlsHandshakeCompletedHook` or similar? Or using the `...Start/End...` scheme?" +1187,"@@ -157,6 +157,7 @@ namespace Nethermind.Blockchain.Synchronization + + if (headersSynced > 0) + { ++ _blockTree.Flush(); + _syncReport.FullSyncBlocksDownloaded.Update(_blockTree.BestSuggestedHeader?.Number ?? 0); + _syncReport.FullSyncBlocksKnown = bestPeer.HeadNumber; + }","it introduces a lot of complexity to the state, can we flush straightaway or create a two level flush store where the questions are read form unflushed data?" +1188,"@@ -220,10 +220,10 @@ class JSTree extends AbstractBase + if ('collection' === $type && !$this->collectionsEnabled) { + $type = 'record'; + } +- $url = $this->getUrlFromRouteCache($type, $node->id); ++ $url = $this->getUrlFromRouteCache($type, urlencode($node->id)); + return $type === 'collection' + ? $url . '#tabnav' +- : $url . '#tree-' . preg_replace('/\W/', '-', $node->id); ++ : $url . '#tree-' . preg_replace('/\W/', '-', urlencode($node->id)); + } + } + ","There are two calls to getUrlFromRouteCache, but you're only urlencoding one of them. Is that intentional? Would it make more sense to do the url-encoding inside the getUrlFromRouteCache function?" +1189,"@@ -142,7 +142,11 @@ class EditorManager { + + if (editorClass) { + this.activeEditor = getEditorInstance(editorClass, this.instance); ++ this.activeEditor.row = row; // pre-preparation needed by getEditedCell ++ this.activeEditor.col = col; + const td = this.activeEditor.getEditedCell(); ++ this.activeEditor.row = null; // restore the un-initialized state ++ this.activeEditor.col = null; + this.activeEditor.prepare(row, col, prop, td, originalValue, cellProperties); + + } else {",Maybe we can use `this.instance.getCell` with `topMost` flag to get `TD` element? +1190,"@@ -280,7 +280,11 @@ func (cs *ChainService) HandleAction(_ context.Context, actPb *iotextypes.Action + if err := act.LoadProto(actPb); err != nil { + return err + } +- return cs.actpool.Add(act) ++ err := cs.actpool.Add(act) ++ if err != nil { ++ log.L().Info(err.Error()) ++ } ++ return err + } + + // HandleBlock handles incoming block request.",Change this to Debug Level +1191,"@@ -521,9 +521,9 @@ namespace NLog.Targets + { + _allLayoutsAreThreadSafe = _allLayouts.All(layout => layout.ThreadSafe); + } +- StackTraceUsage = _allLayouts.DefaultIfEmpty().Max(layout => layout?.StackTraceUsage ?? StackTraceUsage.None); +- if (this is IUsesStackTrace usesStackTrace && usesStackTrace.StackTraceUsage > StackTraceUsage) +- StackTraceUsage = usesStackTrace.StackTraceUsage; ++ StackTraceUsage = _allLayouts.DefaultIfEmpty().Aggregate(StackTraceUsage.None, (seed,layout) => seed | (layout?.StackTraceUsage ?? StackTraceUsage.None)); ++ if (this is IUsesStackTrace usesStackTrace) ++ StackTraceUsage |= usesStackTrace.StackTraceUsage; + _scannedForLayouts = true; + } + ","I refactored the Aggregate, those are hard to read" +1192,"@@ -290,14 +290,6 @@ describe('region', function() { + assert.isTrue(checkEvaluate.apply(checkContext, checkArgs)); + }); + +- it('treats iframe elements as regions', function() { +- var checkArgs = checkSetup( +- '
    Content
    ' +- ); +- +- assert.isTrue(checkEvaluate.apply(checkContext, checkArgs)); +- }); +- + it('returns the outermost element as the error', function() { + var checkArgs = checkSetup( + '

    This is random content.

    Introduction

    '","This is now done in the after method, so this test won't pass any more." +1193,"@@ -152,10 +152,14 @@ class ApplicationController < ActionController::Base + # have we identified the user? + if @user + # check if the user has been banned +- if @user.blocks.active.exists? +- # NOTE: need slightly more helpful message than this. ++ user_block = @user.blocks.active.take ++ unless user_block.nil? + set_locale +- report_error t(""application.setup_user_auth.blocked""), :forbidden ++ if @user.blocks.active.take.zero_hour? ++ report_error t(""application.setup_user_auth.blocked_zero_hour""), :forbidden ++ else ++ report_error t(""application.setup_user_auth.blocked""), :forbidden ++ end + end + + # if the user hasn't seen the contributor terms then don't",What was the point of creating `user_block` if you're then not going to use it ;-) +1194,"@@ -22,9 +22,6 @@ from decorator import decorator + import types + import logging + +-from databricks.koalas.frame import PandasLikeDataFrame +-from databricks.koalas.series import PandasLikeSeries +- + logger = logging.getLogger('spark') + + _TOUCHED_TEST = ""_pandas_updated""","@ueshin, I thought we can remove this entire file. Does that require some more works?" +1195,"@@ -39,7 +39,7 @@ def evaluateTokens(requestContext, tokens): + return float(tokens.number.scientific[0]) + + elif tokens.string: +- return str(tokens.string)[1:-1] ++ return unicode(tokens.string)[1:-1] + + elif tokens.boolean: + return tokens.boolean[0] == 'true'",Just `return tokens.string[1:-1]` is enough +1196,"@@ -0,0 +1,3 @@ ++resources :quizzes, only: [:show] do ++ resources :questions, only: [:show] ++end",1 trailing blank lines detected. +1197,"@@ -29,7 +29,7 @@ public class LeftButton extends Button { + super(name); + this.name = name; + this.getStyleClass().add(""leftButton""); +- this.setPrefWidth(Double.MAX_VALUE); ++ this.setMaxWidth(Double.MAX_VALUE); + this.setAlignment(Pos.CENTER_LEFT); + this.setPadding(new Insets(2)); + }",Isn't this the default max width? In any case I would prefer to see these definitions in the css files. +1198,"@@ -34,10 +34,11 @@ func redirParse(c *caddy.Controller) ([]Rule, error) { + cfg := httpserver.GetConfig(c) + + initRule := func(rule *Rule, defaultCode string, args []string) error { +- if cfg.TLS.Enabled { +- rule.FromScheme = ""https"" +- } else { +- rule.FromScheme = ""http"" ++ rule.FromScheme = func() string { ++ if cfg.TLS.Enabled { ++ return ""https"" ++ } ++ return ""http"" + } + + var (","Is this thread-safe? (If not, and if the solution is to introduce locking, let's reconsider how we do the scheme changing instead...)" +1199,"@@ -21,8 +21,8 @@ + # IN THE SOFTWARE. + #------------------------------------------------------------------------------- + from datatable.lib._datatable import ( +- Ftrl, + aggregate, ++ Ftrl, + kfold, + kfold_random, + )",Looks like this file has tabs instead of spaces. +1200,"@@ -649,6 +649,19 @@ func (engine *DockerTaskEngine) deleteTask(task *apitask.Task) { + } + } + ++ for _, container := range task.Containers { ++ for _, resource := range container.GetResources() { ++ err := resource.Cleanup() ++ if err != nil { ++ seelog.Warnf(""Task engine [%s]/[%s]: unable to cleanup resource %s: %v"", ++ task.Arn, container.Name, resource.GetName(), err) ++ } else { ++ seelog.Infof(""Task engine [%s]/[%s]: resource %s cleanup complete"", ++ task.Arn, container.Name, resource.GetName()) ++ } ++ } ++ } ++ + if execcmd.IsExecEnabledTask(task) { + // cleanup host exec agent log dirs + if tID, err := task.GetID(); err != nil {",Hmm should we clean up container resources before task resources here? or the order does not really matter here? +1201,"@@ -44,7 +44,6 @@ def temporary_download_dir(quteproc, tmpdir): + unwritable.ensure(dir=True) + unwritable.chmod(0) + +- + @bdd.given(""I clean old downloads"") + def clean_old_downloads(quteproc): + quteproc.send_cmd(':download-cancel --all')",Please undo this :wink: +1202,"@@ -25,6 +25,12 @@ class ApiClient < ActiveRecord::Base + include DeviseInvitable::Inviter + include ValidationMessages + ++ # ================ ++ # = Associations = ++ # ================ ++ ++ has_many :plans ++ + # If the Client_id or client_secret are nil generate them + before_validation :generate_credentials, + if: Proc.new { |c| c.client_id.blank? || c.client_secret.blank? }",thanks for adding this missing association +1203,"@@ -11,6 +11,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Https + public static class HttpsApplicationBuilderExtensions + { + public static IApplicationBuilder UseKestrelHttps(this IApplicationBuilder app, X509Certificate2 cert) ++ { ++ return app.UseKestrelHttps(new HttpsConnectionFilterOptions { ServerCertificate = cert}); ++ } ++ ++ public static IApplicationBuilder UseKestrelHttps(this IApplicationBuilder app, HttpsConnectionFilterOptions options) + { + var serverInfo = app.ServerFeatures.Get(); + ",Should I remove this in favor of the HttpsConnectionFilterOptions overload? +1204,"@@ -109,6 +109,15 @@ class DbalStatusQuery implements StatusQueryInterface + return array_values($result); + } + ++ public function getMaxIndex(): ?int ++ { ++ return $this->connection->createQueryBuilder() ++ ->select('max(index)') ++ ->from(self::STATUS_TABLE) ++ ->execute() ++ ->fetchOne(); ++ } ++ + private function getQuery(Language $language): QueryBuilder + { + return $this->connection->createQueryBuilder()","This shode be nullable, there alway sholud be at least one status in system , if not exist that mean data problme" +1205,"@@ -32,6 +32,10 @@ class Auth extends Controller + public function __construct() + { + parent::__construct(); ++ ++ // Add JS File to unistall SW to avoid Cookie Cache Issues when Signin, see github issue: #3707 ++ $this->addJs('../../../modules/backend/assets/js/auth/unistall-sw.js'); ++ + $this->layout = 'auth'; + } + ",Spaces not tabs +1206,"@@ -160,6 +160,15 @@ class FsDriverNode extends FsDriverBase { + } + } + ++ async readDir(path) { ++ try { ++ // return fs.readdirSync(path, {withFileTypes: true}).map(e => e.name); // From Node v10 ++ return fs.readdirSync(path); // For Node v8 ++ } catch (error) { ++ throw this.fsErrorToJsError_(error, path); ++ } ++ } ++ + // Always overwrite destination + async copy(source, dest) { + try {","To get the files inside a directory, please use `readDirStats()`." +1207,"@@ -34,8 +34,11 @@ const LocalConfigFileName string = "".plzconfig.local"" + // for a particular machine (eg. build machine with different caching behaviour). + const MachineConfigFileName = ""/etc/plzconfig"" + +-const TestContainerDocker = ""docker"" +-const TestContainerNone = ""none"" ++const ( ++ ContainerImplementationNone = ""none"" ++ ContainerImplementationDocker = ""docker"" ++ ContainerImplementationPlz = ""plz"" ++) + + func readConfigFile(config *Configuration, filename string) error { + log.Debug(""Reading config from %s..."", filename)","might be worth to call these `Isolation` instead of containers here and when presented to the user -- docker/rkt , in addition to cgroups and namespaces, also provide image discovery and filesystem preparation; there's also the security context and probably 1-2 other small things" +1208,"@@ -0,0 +1,5 @@ ++// Copyright 2020 The Swarm Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package batchstore_test","File is empty, consider removing?" +1209,"@@ -237,6 +237,16 @@ def _refresh_credentials(): + return result + + ++def logged_in(): ++ """""" ++ Return registry URL if Quilt client is authenticated. Otherwise ++ return `None`. ++ """""" ++ url = get_registry_url() ++ if url in _load_auth(): ++ return url ++ ++ + class QuiltProvider(CredentialProvider): + METHOD = 'quilt-registry' + CANONICAL_NAME = 'QuiltRegistry'","This seems to return the registry_url. The more meaningful URL is the catalog URL, which is the URL the user specifies in `quilt3.login`. The username might also be as useful here if not more useful." +1210,"@@ -23,8 +23,9 @@ type Config struct { + L1CrossDomainMessengerAddress common.Address + L1FeeWalletAddress common.Address + AddressManagerOwnerAddress common.Address +- L1ETHGatewayAddress common.Address + GasPriceOracleOwnerAddress common.Address ++ L1StandardBridgeAddress common.Address ++ GasPriceOracleAddress common.Address + // Turns on checking of state for L2 gas price + EnableL2GasPolling bool + // Deployment Height of the canonical transaction chain",Was the addition of `GasPriceOracleAddress` here erroneous? +1211,"@@ -121,6 +121,11 @@ module Beaker + :project => 'Beaker', + :department => 'unknown', + :created_by => ENV['USER'] || ENV['USERNAME'] || 'unknown', ++ :host_tags => { ++ :project => 'Beaker', ++ :department => 'unknown', ++ :created_by => ENV['USER'] || ENV['USERNAME'] || 'unknown' ++ }, + :openstack_api_key => ENV['OS_PASSWORD'], + :openstack_username => ENV['OS_USERNAME'], + :openstack_auth_url => ""#{ENV['OS_AUTH_URL']}/tokens"",","I believe that you are going to have to do some work here to get the env var support for these values to still work correctly, otherwise they will get stored as :department instead of host_tags[:department]." +1212,"@@ -149,8 +149,12 @@ public class SessionStore implements + if (BuildConfig.DEBUG) { + mStoreSubscription = ComponentsAdapter.get().getStore().observeManually(browserState -> { + Log.d(LOGTAG, ""Session status BEGIN""); +- browserState.getTabs().forEach(tabSessionState -> Log.d(LOGTAG, ""BrowserStore Session: "" + tabSessionState.getId())); +- mSessions.forEach(session -> Log.d(LOGTAG, ""SessionStore Session: "" + session.getId())); ++ for (int i=0; i 100 maybe too much, 200 ish to 500ish maybe a good option" +1225,"@@ -60,5 +60,5 @@ func (a *ChecksumAddress) UnmarshalText(text []byte) error { + // MarshalText implements the encoding.TextMarshaler interface + func (a ChecksumAddress) MarshalText() (text []byte, err error) { + addr := basics.Address(a) +- return []byte(addr.GetChecksumAddress().String()), nil ++ return []byte(addr.String()), nil + }",Any reason we need to keep this package's `ChecksumAddress` type or can we get rid of it too? +1226,"@@ -248,7 +248,7 @@ events.on(serverNotifications, 'RestartRequired', function (e, apiClient) { + [ + { + action: 'restart', +- title: globalize.translate('ButtonRestart'), ++ title: globalize.translate('HeaderRestart'), + icon: getIconUrl() + } + ];","Above the one that was picked was the Button* prefix, and here it's the Header* prefix. Maybe the Button prefix is more general." +1227,"@@ -1250,7 +1250,7 @@ namespace Nethermind.Blockchain + + public Keccak HeadHash => Head?.Hash; + public Keccak GenesisHash => Genesis?.Hash; +- public Keccak PendingHash => BestSuggestedHeader?.Hash; ++ public Keccak PendingHash => Head?.Hash; + + public Block FindBlock(Keccak blockHash, BlockTreeLookupOptions options) + {","I might prefer changing: public Block FindPendingBlock() => FindBlock(PendingHash, BlockTreeLookupOptions.None); public BlockHeader FindPendingHeader() => FindHeader(PendingHash, BlockTreeLookupOptions.None); in IBlockFinder, what do you think?" +1228,"@@ -206,6 +206,7 @@ type SyncStatus struct { + type SyncSetCommonSpec struct { + // Resources is the list of objects to sync from RawExtension definitions. + // +optional ++ // +kubebuilder:pruning:PreserveUnknownFields + Resources []runtime.RawExtension `json:""resources,omitempty""` + + // ResourceApplyMode indicates if the Resource apply mode is ""Upsert"" (default) or ""Sync"".",This is necessary due to a bug in 4.7. Follow HIVE-1561 for getting rid of it. +1229,"@@ -2,8 +2,10 @@ class Topic < ActiveRecord::Base + # Associations + has_many :classifications + with_options(through: :classifications, source: :classifiable) do |options| ++ options.has_many :exercises, source_type: 'Exercise' + options.has_many :products, source_type: 'Product' + options.has_many :topics, source_type: 'Topic' ++ options.has_many :videos, source_type: 'Video' + options.has_many :workshops, source_type: 'Workshop' + end + has_one :trail",Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. +1230,"@@ -38,7 +38,7 @@ + #include ""common/xutil.h"" + #include ""xkb.h"" + +-/* XStringToKeysym() and XKeysymToString */ ++/* XStringToKeysym() */ + #include + #include + #include ",Some day (tm) I will also get rid of that one. But today is not that day... +1231,"@@ -206,6 +206,17 @@ class CombineAssets + // Disable cache always + $this->storagePath = null; + ++ // Prefix all assets ++ if($localPath) { ++ if (substr($localPath, -1) !== '/') { ++ $localPath = $localPath.'/'; ++ } ++ $assets = array_map(function($asset) use ($localPath) { ++ if (substr($asset, 0, 1) === '@') return $asset; ++ return $localPath.$asset; ++ }, $assets); ++ } ++ + list($assets, $extension) = $this->prepareAssets($assets); + + $rewritePath = File::localToPublic(dirname($destination));",Add a space between if and opening parenthesis please (i.e. `if (`) +1232,"@@ -827,8 +827,9 @@ class Series(_Frame, IndexOpsMixin, Generic[T]): + Name: my_name, dtype: int64 + """""" + if index is None: +- return self +- scol = self._scol.alias(index) ++ scol = self._scol ++ else: ++ scol = self._scol.alias(index) + if kwargs.get('inplace', False): + self._internal = self._internal.copy(scol=scol) + return self",nit: `rename` instead of `alias`? +1233,"@@ -113,11 +113,17 @@ func (d *Driver) freeDevices() (string, string, error) { + return """", """", err + } + devPrefix := ""/dev/sd"" ++ + for _, dev := range self.BlockDeviceMappings { + if dev.DeviceName == nil { + return """", """", fmt.Errorf(""Nil device name"") + } + devName := *dev.DeviceName ++ ++ // sda1 is reserved for the root device, skip ++ if devName == ""/dev/sda1"" { ++ continue ++ } + if !strings.HasPrefix(devName, devPrefix) { + devPrefix = ""/dev/xvd"" + if !strings.HasPrefix(devName, devPrefix) {",Per AWS docs EC instances have the root mounted at /dev/sda1. This label should be skipped. +1234,"@@ -92,7 +92,6 @@ func (q *ChannelEventQueue) dispatchMessage() { + event := model.MessageToEvent(&msg) + select { + case rChannel <- event: +- default: + } + } + }","I'm not sure it is a better way to address lose message, if wait here, edge controller cant process message, event from watching api-server will be lost yet, right?" +1235,"@@ -539,11 +539,12 @@ class EAP_MD5(EAP): + ByteEnumField(""code"", 1, eap_codes), + ByteField(""id"", 0), + FieldLenField(""len"", None, fmt=""H"", length_of=""optional_name"", +- adjust=lambda p, x: x + p.value_size + 6), ++ adjust=lambda p, x: (x + p.value_size + 6) if p.value_size is not None else 6), + ByteEnumField(""type"", 4, eap_types), +- FieldLenField(""value_size"", 0, fmt=""B"", length_of=""value""), ++ FieldLenField(""value_size"", None, fmt=""B"", length_of=""value""), + XStrLenField(""value"", '', length_from=lambda p: p.value_size), +- XStrLenField(""optional_name"", '', length_from=lambda p: p.len - p.value_size - 6) ++ XStrLenField(""optional_name"", '', ++ length_from=lambda p: (p.len - p.value_size - 6) if p.len is not None and p.value_size is not None else 0) + ] + + ","Please keep the correct alignment, it seems broken now (at least in Github). Can you reverse the test (`if p.value_size is None`)? Also, do you want `6` when `p.value_size is None` or `x + 6`? Maybe, in that case, something like `lambda p, x: x + 6 + (0 if p.value_size is None else p.value_size)` would be easier to read. Or even easier: `lambda p, x: x + 6 + (p.value_size or 0)`." +1236,"@@ -238,6 +238,10 @@ type Container struct { + + Secrets []*Secret `locationName:""secrets"" type:""list""` + ++ StartTimeout *int64 `locationName:""startTimeout"" type:""integer""` ++ ++ StopTimeout *int64 `locationName:""stopTimeout"" type:""integer""` ++ + VolumesFrom []*VolumeFrom `locationName:""volumesFrom"" type:""list""` + } + ",Can we make sure ECS service treats it as int64 as well? +1237,"@@ -178,6 +178,15 @@ class UIProperty(UIA): + return value + return value.replace(CHAR_LTR_MARK,'').replace(CHAR_RTL_MARK,'') + ++class ReadOnlyEditBox(IAccessible): ++#Used for read-only edit boxes in a properties window. ++#These can contain dates that include unwanted left-to-right and right-to-left indicator characters. ++ ++ def _get_windowText(self): ++ WindowText = super(ReadOnlyEditBox, self).windowText ++ if WindowText is not None and controlTypes.STATE_READONLY in self.states: ++ return WindowText.replace(CHAR_LTR_MARK,'').replace(CHAR_RTL_MARK,'') ++ return WindowText + + class AppModule(appModuleHandler.AppModule): + ","Please follow the naming convention for variables, i.e. `windowText`." +1238,"@@ -21,8 +21,8 @@ import ( + + yaml ""github.com/ghodss/yaml"" + ""github.com/openebs/maya/pkg/apis/openebs.io/v1alpha1"" ++ castv1alpha1 ""github.com/openebs/maya/pkg/castemplate/v1alpha1"" + m_k8s_client ""github.com/openebs/maya/pkg/client/k8s"" +- ""github.com/openebs/maya/pkg/engine"" + menv ""github.com/openebs/maya/pkg/env/v1alpha1"" + ""github.com/pkg/errors"" + v1_storage ""k8s.io/api/storage/v1""",alias can be `cast` +1239,"@@ -97,13 +97,14 @@ static h2o_iovec_t events_status_final(void *priv, h2o_globalconf_t *gconf, h2o_ + "" \""http2-errors.inadequate-security\"": %"" PRIu64 "", \n"" + "" \""http2.read-closed\"": %"" PRIu64 "", \n"" + "" \""http2.write-closed\"": %"" PRIu64 "", \n"" +- "" \""ssl.errors\"": %"" PRIu64 ""\n"", ++ "" \""ssl.errors\"": %"" PRIu64 "", \n"" ++ "" \""memory.mmap_errors\"": %"" PRIu64 ""\n"", + H1_AGG_ERR(400), H1_AGG_ERR(403), H1_AGG_ERR(404), H1_AGG_ERR(405), H1_AGG_ERR(416), H1_AGG_ERR(417), + H1_AGG_ERR(500), H1_AGG_ERR(502), H1_AGG_ERR(503), H2_AGG_ERR(PROTOCOL), H2_AGG_ERR(INTERNAL), + H2_AGG_ERR(FLOW_CONTROL), H2_AGG_ERR(SETTINGS_TIMEOUT), H2_AGG_ERR(STREAM_CLOSED), H2_AGG_ERR(FRAME_SIZE), + H2_AGG_ERR(REFUSED_STREAM), H2_AGG_ERR(CANCEL), H2_AGG_ERR(COMPRESSION), H2_AGG_ERR(CONNECT), + H2_AGG_ERR(ENHANCE_YOUR_CALM), H2_AGG_ERR(INADEQUATE_SECURITY), esc->h2_read_closed, esc->h2_write_closed, +- esc->ssl_errors); ++ esc->ssl_errors, (uint64_t)mmap_errors); + pthread_mutex_destroy(&esc->mutex); + free(esc); + return ret;","Let's use `%zu` instead of casting to `uint64_t` and using `PRIu64`. The alternative is to change the type of `mmap_errors` to `uint64_t`, though I'd prefer not doing that because some 32-bit platforms might not provide atomic operation support for `uint64_t`." +1240,"@@ -57,7 +57,7 @@ import javax.lang.model.element.Name; + name = ""CatchSpecificity"", + link = ""https://github.com/palantir/gradle-baseline#baseline-error-prone-checks"", + linkType = BugPattern.LinkType.CUSTOM, +- severity = BugPattern.SeverityLevel.SUGGESTION, ++ severity = BugPattern.SeverityLevel.WARNING, + summary = ""Prefer more specific error types than Exception and Throwable. When methods are updated to throw new"" + + "" checked exceptions they expect callers to handle failure types explicitly. Catching broad"" + + "" types defeats the type system. By catching the most specific types possible we leverage""",I recall there being a reason we had this one set only to suggeation. @carterkozak do you remember why? or is my memory getting corrupted? +1241,"@@ -72,7 +72,7 @@ class CppGenerator : public BaseGenerator { + } + for (auto it = parser_.included_files_.begin(); + it != parser_.included_files_.end(); ++it) { +- auto noext = flatbuffers::StripExtension(it->first); ++ auto noext = flatbuffers::StripExtension(it->second); + auto basename = flatbuffers::StripPath(noext); + if (basename != file_name_) { + code_ += ""#include \"""" + parser_.opts.include_prefix +",This should now be made into `if (it->second.empty())` ? +1242,"@@ -126,13 +126,19 @@ class WebEngineSearch(browsertab.AbstractSearch): + def __init__(self, parent=None): + super().__init__(parent) + self._flags = QWebEnginePage.FindFlags(0) ++ self.num_of_searches = 0 + + def _find(self, text, flags, callback, caller): + """"""Call findText on the widget."""""" + self.search_displayed = True ++ self.num_of_searches += 1 + + def wrapped_callback(found): + """"""Wrap the callback to do debug logging."""""" ++ self.num_of_searches -= 1 ++ if self.num_of_searches > 0: ++ return ++ + found_text = 'found' if found else ""didn't find"" + if flags: + flag_text = 'with flags {}'.format(debug.qflags_key(","Do we need to worry about a race condition on this decrement (@The-Compiler)? I'm not sure how the python callbacks work, so this might not need to be something to worry about." +1243,"@@ -100,7 +100,7 @@ func TestMultiplePropagators(t *testing.T) { + // generates the valid span context out of thin air + { + ctx := ootaProp.Extract(bg, ns) +- sc := trace.RemoteSpanContextFromContext(ctx) ++ sc := trace.SpanContextFromContext(ctx) + require.True(t, sc.IsValid(), ""oota prop failed sanity check"") + } + // sanity check for real propagators, ensuring that they",Should these assert that the extracted `SpanContext` is remote? +1244,"@@ -27,6 +27,9 @@ class ApproxMaxIoUAssigner(MaxIoUAssigner): + ignoring any bboxes. + ignore_wrt_candidates (bool): Whether to compute the iof between + `bboxes` and `gt_bboxes_ignore`, or the contrary. ++ match_low_quality (bool): Whether to allow quality matches. This is ++ usually allowed for RPN and single stage detectors, but not allowed ++ in the second stage. + gpu_assign_thr (int): The upper bound of the number of GT for GPU + assign. When the number of gt is above this threshold, will assign + on CPU device. Negative values mean not assign on CPU.",typo: allow low quality matches. +1245,"@@ -49,7 +49,7 @@ func ResolveDataDir(dataDir string) (string, error) { + return filepath.Join(dataDir, ""server""), err + } + +-func StartServer(ctx context.Context, config *Config) error { ++func StartServer(ctx context.Context, config *Config, cfg *cmds.Server) error { + if err := setupDataDirAndChdir(&config.ControlConfig); err != nil { + return err + }","At some point we need to condense down and refactor our ""configs"" as we have too many in too many places and we're starting to get more illegible code. No change necessary but calling out for future reference." +1246,"@@ -39,7 +39,8 @@ module Blacklight + def options + { + class: classes, +- ""aria-hidden"": (true if aria_hidden) ++ ""aria-hidden"": (true if aria_hidden), ++ ""aria-label"": icon_label + } + end + ",Can we add the `if label` conditional to this please? +1247,"@@ -40,6 +40,7 @@ setup( + packages=['databricks', 'databricks.koalas', 'databricks.koalas.missing'], + extras_require={ + 'spark': ['pyspark>=2.4.0'], ++ 'mlflow': ['mlflow>=0.2.0'], + }, + python_requires='>=3.5', + install_requires=[","@thunterdb, can we increase the minimal version to almost the latest ones? I was thinking people will mostly use the latest version of mlflow" +1248,"@@ -669,6 +669,8 @@ const REGISTERED_HOOKS = [ + * @param {CellRange} sourceRange The range values will be filled from. + * @param {CellRange} targetRange The range new values will be filled into. + * @param {string} direction Declares the direction of the autofill. Possible values: `up`, `down`, `left`, `right`. ++ * @param {boolean} hasFillDataChanged Indicates whether the original fillData has been changed in ++ * the `beforeAutofill` hook. + */ + 'afterAutofill', + ","If the last argument is going to be removed, why would we add it to the API docs? Shouldn't it be private for internal use?" +1249,"@@ -37,13 +37,18 @@ from .execution_context import ( + SystemPipelineExecutionContext, + ) + +- + from .errors import DagsterInvariantViolationError + + from .events import construct_event_logger + + from .execution_plan.create import create_execution_plan_core + ++from .execution_plan.intermediates_manager import ( ++ FileSystemIntermediateManager, ++ InMemoryIntermediatesManager, ++ IntermediatesManager, ++) ++ + from .execution_plan.objects import ( + ExecutionPlan, + ExecutionStepEvent,",`Intermediates` or `Intermediate` +1250,"@@ -95,6 +95,8 @@ class visibility_of(object): + + + def _element_if_visible(element, visibility=True): ++ if isinstance(element, str) or isinstance(element, dict): ++ raise StaleElementReferenceException(""Invalid locator"") + return element if element.is_displayed() == visibility else False + + ",This is not the right exception class. There is an InvalidSelectorException class that covers bad locators. +1251,"@@ -52,8 +52,9 @@ func (c *Cluster) Bootstrap(ctx context.Context, snapshot bool) error { + // instance of etcd in the event that etcd certificates are unavailable, + // reading the data, and comparing that to the data on disk, all the while + // starting normal etcd. +- isHTTP := c.config.JoinURL != """" && c.config.Token != """" +- if isInitialized && !isHTTP { ++ // isHTTP := c.config.JoinURL != """" && c.config.Token != """" ++ if isInitialized { ++ logrus.Info(""Only reconciling with datastore"") + tmpDataDir := filepath.Join(c.config.DataDir, ""db"", ""tmp-etcd"") + os.RemoveAll(tmpDataDir) + if err := os.Mkdir(tmpDataDir, 0700); err != nil {","If this code isn't needed, it should be removed." +1252,"@@ -145,10 +145,13 @@ func (md *metricsDriver) uploadMetrics(ctx context.Context, protoMetrics []*metr + if md.metricsClient == nil { + return errNoClient + } +- _, err := md.metricsClient.Export(ctx, &colmetricpb.ExportMetricsServiceRequest{ +- ResourceMetrics: protoMetrics, +- }) +- return err ++ req := func(ctx context.Context) error { ++ _, err := md.metricsClient.Export(ctx, &colmetricpb.ExportMetricsServiceRequest{ ++ ResourceMetrics: protoMetrics, ++ }) ++ return err ++ } ++ return doRequest(ctx, req, md.connection.cfg.RetrySettings, md.connection.stopCh) + }() + if err != nil { + md.connection.setStateDisconnected(err)",Should the `doRequest` func be a method on the `connection` type instead of passing state from the type? +1253,"@@ -99,8 +99,8 @@ var _ = Describe(""init flow"", func() { + Expect(len(app.Variables)).To(Equal(5)) + expectedVars := map[string]string{ + ""ECS_CLI_APP_NAME"": appName, +- ""ECS_CLI_ENVIRONMENT_NAME"": ""test"", +- ""ECS_CLI_LB_DNS"": strings.TrimPrefix(app.Routes[0].URL, ""http://""), ++ ""COPILOT_ENVIRONMENT_NAME"": ""test"", ++ ""COPILOT_LB_DNS"": strings.TrimPrefix(app.Routes[0].URL, ""http://""), + ""ECS_CLI_PROJECT_NAME"": projectName, + ""ECS_APP_DISCOVERY_ENDPOINT"": fmt.Sprintf(""%s.local"", projectName), + }",we'll probably tackle these e2e tests at the end +1254,"@@ -0,0 +1,19 @@ ++// Licensed to the .NET Foundation under one or more agreements. ++// The .NET Foundation licenses this file to you under the MIT license. ++// See the LICENSE file in the project root for more information. ++ ++using BenchmarkDotNet.Attributes; ++using MicroBenchmarks; ++ ++namespace System.Net.Tests ++{ ++ [BenchmarkCategory(Categories.CoreFX)] ++ public class DnsTests ++ { ++ [Benchmark] ++ public IPHostEntry GetHostEntry() => Dns.GetHostEntry(""34.206.253.53""); ++ ++ [Benchmark] ++ public string GetHostName() => Dns.GetHostName(); ++ } ++}",what is this address pointing to? what are we measuring here? I want to have a better understanding. +1255,"@@ -101,7 +101,8 @@ public class JdbcFlowTriggerInstanceLoaderImpl implements FlowTriggerInstanceLoa + + ""project_json, flow_exec_id \n"" + + ""FROM execution_dependencies JOIN (\n"" + + ""SELECT trigger_instance_id FROM execution_dependencies WHERE trigger_instance_id not in (\n"" +- + ""SELECT distinct(trigger_instance_id) FROM execution_dependencies WHERE dep_status = 0 or dep_status = 4)\n"" ++ + ""SELECT distinct(trigger_instance_id) FROM execution_dependencies WHERE dep_status ="" ++ + "" 0 or dep_status = 3)\n"" + + ""GROUP BY trigger_instance_id\n"" + + ""ORDER BY min(starttime) desc limit %s) temp on execution_dependencies"" + + "".trigger_instance_id in (temp.trigger_instance_id);"";","Would it be better to pass the dependency status as the parameter into the SQL string? In case the enum value is changed in the future, we don't need to change the code here." +1256,"@@ -1,3 +1,9 @@ ++// Copyright 2017 Keybase Inc. All rights reserved. ++// Use of this source code is governed by a BSD ++// license that can be found in the LICENSE file. ++ ++// +build windows ++ + package libdokan + + import (",Hah I had `gorename` failing without this too. +1257,"@@ -597,6 +597,12 @@ namespace Datadog.Trace + writer.WritePropertyName(""appsec_blocking_enabled""); + writer.WriteValue(Security.Instance.Settings.BlockingEnabled); + ++ writer.WritePropertyName(""rules_file_path""); ++ writer.WriteValue(Security.Instance.Settings.Rules ?? ""(none)""); ++ ++ writer.WritePropertyName(""libddwaf_version""); ++ writer.WriteValue(Security.Instance.DdlibWafVersion?.ToString() ?? ""(none)""); ++ + writer.WriteEndObject(); + } + ",maybe prefix these with `appsec_` for consistency? +1258,"@@ -7,11 +7,19 @@ import ( + ""crypto/x509"" + ""errors"" + ""fmt"" ++ ""github.com/spiffe/spire/pkg/common/profiling"" ++ ""net/http"" ++ _ ""net/http/pprof"" + ""net/url"" + ""path"" ++ ""runtime"" ++ ++ ""strconv"" + ""sync"" + ""syscall"" + ++ _ ""golang.org/x/net/trace"" ++ + ""github.com/spiffe/spire/pkg/agent/catalog"" + ""github.com/spiffe/spire/pkg/agent/endpoints"" + ""github.com/spiffe/spire/pkg/agent/manager""",nit: this should be down further with the other github imports +1259,"@@ -560,6 +560,11 @@ def main(): + else: + log.debug(""initializing updateCheck"") + updateCheck.initialize() ++ # If running from source, try to disconnect from the console we may have been executed in. ++ # NVDA may reconnect to read it later, ++ # but it is better to assume we are not connected to anything at the start. ++ if ctypes.windll.kernel32.FreeConsole() != 0: ++ log.debug(""Freed from parent console process."") + log.info(""NVDA initialized"") + postNvdaStartup.notify() + ",Why is this change necessary or related to the rest of the PR? +1260,"@@ -31,7 +31,7 @@ class ConsoleReport extends Report + $issue_string .= 'INFO'; + } + +- $issue_reference = $issue_data->link ? ' (see ' . $issue_data->link . ')' : ''; ++ $issue_reference = $issue_data->link ? ' - see: ' . $issue_data->link : ''; + + $issue_string .= ': ' . $issue_data->type + . ' - ' . $issue_data->file_name . ':' . $issue_data->line_from . ':' . $issue_data->column_from","Hm, I wonder if the `see:` prefix is even necessary?" +1261,"@@ -261,7 +261,13 @@ import 'emby-button'; + + minutes = minutes || 1; + +- miscInfo.push(`${Math.round(minutes)} mins`); ++ if (item.UserData?.PlaybackPositionTicks) { ++ let remainingMinutes = (item.RunTimeTicks - item.UserData.PlaybackPositionTicks) / 600000000; ++ remainingMinutes = remainingMinutes || 1; ++ miscInfo.push(`${Math.round(minutes)} mins (${Math.round(remainingMinutes)} remaining)`); ++ } else { ++ miscInfo.push(`${Math.round(minutes)} mins`); ++ } + } + } + ",This should be translated. +1262,"@@ -294,13 +294,15 @@ class Booster { + void ResetConfig(const char* parameters) { + UNIQUE_LOCK(mutex_) + auto param = Config::Str2Map(parameters); +- if (param.count(""num_class"")) { ++ Config new_config; ++ new_config.Set(param); ++ if (param.count(""num_class"") && new_config.num_class != config_.num_class) { + Log::Fatal(""Cannot change num_class during training""); + } +- if (param.count(""boosting"")) { ++ if (param.count(""boosting"") && new_config.boosting != config_.boosting) { + Log::Fatal(""Cannot change boosting during training""); + } +- if (param.count(""metric"")) { ++ if (param.count(""metric"") && new_config.metric != config_.metric) { + Log::Fatal(""Cannot change metric during training""); + } + CheckDatasetResetConfig(config_, param);","I originally had this PR only changing the R package, but then ran into this error > Error: [LightGBM] [Fatal] Cannot change metric during training This is thrown even if you aren't actually CHANGING `metric`. I think the change here in `c_api` is closer to the desired behavior, only throwing an error if the parameter is being changed." +1263,"@@ -356,9 +356,9 @@ describe 'run_task' do + + is_expected.to run.with_params(task_name, hostname, task_params).and_raise_error( + Puppet::ParseError, +- /Task\ test::params:\n ++ %r{Task\ test::params:\n + \s*has\ no\ parameter\ named\ 'foo'\n +- \s*has\ no\ parameter\ named\ 'bar'/x ++ \s*has\ no\ parameter\ named\ 'bar'}x + ) + end + ","These changes are just to make cli_spec a little more readable for VS Code users, as there's a bug with the Ruby plugin's syntax highlighting when you use multi-line regex literals." +1264,"@@ -1564,7 +1564,7 @@ func (r *ReconcileClusterDeployment) mergePullSecrets(cd *hivev1.ClusterDeployme + globalPullSecretName := os.Getenv(constants.GlobalPullSecret) + var globalPullSecret string + if len(globalPullSecretName) != 0 { +- globalPullSecret, err = controllerutils.LoadSecretData(r.Client, globalPullSecretName, constants.HiveNamespace, corev1.DockerConfigJsonKey) ++ globalPullSecret, err = controllerutils.LoadSecretData(r.Client, globalPullSecretName, controllerutils.GetHiveNamespace(), corev1.DockerConfigJsonKey) + if err != nil { + return """", errors.Wrap(err, ""global pull secret could not be retrieved"") + }",Shouldn't the global pull secret by in the namespace of the hive-operator? It is part of the operand. +1265,"@@ -23,11 +23,13 @@ class TestKinesis(unittest.TestCase): + + # create stream and assert 0 consumers + client.create_stream(StreamName=stream_name, ShardCount=1) ++ sleep(1) + assert_consumers(0) + + # create consumer and assert 1 consumer + consumer_name = 'cons1' + response = client.register_stream_consumer(StreamARN=stream_arn, ConsumerName=consumer_name) ++ sleep(1) + self.assertEqual(response['Consumer']['ConsumerName'], consumer_name) + # boto3 converts the timestamp to datetime + self.assertTrue(isinstance(response['Consumer']['ConsumerCreationTimestamp'], datetime))",kinesis-mock applies KINESIS_LATENCY to RegisterStreamConsumer actions so I added a sleep here. +1266,"@@ -145,13 +145,8 @@ std::unique_ptr initKV(std::vector p + LOG(ERROR) << ""Meta version is invalid""; + return nullptr; + } else if (version == nebula::meta::MetaVersion::V1) { +- auto ret = nebula::meta::MetaVersionMan::updateMetaV1ToV2(engine); +- if (!ret.ok()) { +- LOG(ERROR) << ""Update meta from V1 to V2 failed "" << ret; +- return nullptr; +- } +- +- nebula::meta::MetaVersionMan::setMetaVersionToKV(engine, nebula::meta::MetaVersion::V2); ++ LOG(ERROR) << ""Can't upgrade meta from V1 to V3""; ++ return nullptr; + } else if (version == nebula::meta::MetaVersion::V2) { + auto ret = nebula::meta::MetaVersionMan::updateMetaV2ToV3(engine); + if (!ret.ok()) {",Only V1 or V3 is return from `getMetaVersionFromKV`. So where do we call `updateMetaV2ToV3`? +1267,"@@ -26,7 +26,7 @@ func (repo *nodeAttestorRepository) Constraints() catalog.Constraints { + } + + func (repo *nodeAttestorRepository) Versions() []catalog.Version { +- return []catalog.Version{nodeAttestorV0{}} ++ return []catalog.Version{nodeAttestorV1{}} + } + + func (repo *nodeAttestorRepository) LegacyVersion() (catalog.Version, bool) {","I think that V0 is missing here, which will prevent plugins that haven't been converted to work." +1268,"@@ -4,6 +4,7 @@ const withBundleAnalyzer = require(""@next/bundle-analyzer"")({ + }) + + module.exports = withBundleAnalyzer({ ++ // sitemap: () => [{uri: ""/wow"", type: ""pages"", verb: ""get""}], + middleware: [ + sessionMiddleware({ + unstable_isAuthorized: unstable_simpleRolesIsAuthorized,",Should we remove this? +1269,"@@ -6,12 +6,14 @@ import ( + + ""go.uber.org/zap"" + ++ ""github.com/docker/distribution/reference"" + ""github.com/docker/docker/api/types"" + ""github.com/docker/docker/api/types/container"" + ""github.com/docker/docker/api/types/network"" + ""github.com/docker/docker/client"" + ""github.com/gliderlabs/ssh"" + log ""github.com/noxiouz/zapctx/ctxlog"" ++ ""io"" + ) + + type containerDescriptor struct {",Put on top of the import. +1270,"@@ -46,6 +46,7 @@ domReady( () => { + Modules.registerModule( + 'analytics', + { ++ name: 'Analytics', + settingsEditComponent: SettingsEdit, + settingsViewComponent: SettingsView, + setupComponent: SetupMain,","See above, this shouldn't be added." +1271,"@@ -505,8 +505,8 @@ public enum ItemMapping + ITEM_ANGUISH_ORNAMENT_KIT(ANGUISH_ORNAMENT_KIT, NECKLACE_OF_ANGUISH_OR), + ITEM_OCCULT_NECKLACE(OCCULT_NECKLACE, OCCULT_NECKLACE_OR), + ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR), +- ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), +- ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), ++ ITEM_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), ++ ITEM_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), + + // Ensouled heads + ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD),","This'll likely get fixed upstream, we should let them deal with it." +1272,"@@ -93,6 +93,7 @@ type Options struct { + LightNodeLimit int + WelcomeMessage string + Transaction []byte ++ HostFactory func(context.Context, ...libp2p.Option) (host.Host, error) + } + + func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay swarm.Address, addr string, ab addressbook.Putter, storer storage.StateStorer, lightNodes *lightnode.Container, swapBackend handshake.SenderMatcher, logger logging.Logger, tracer *tracing.Tracer, o Options) (*Service, error) {","Somehow, this field does not seems useful for the exposed package api, only for the tests. Would you consider having an unexported field in `hostFactory func(context.Context, ...libp2p.Option) (host.Host, error)` instead to be set only by a new helper function defined in export_test.go. This is just a suggestion, not a hard requirement for the PR approval." +1273,"@@ -111,6 +111,18 @@ class Time { + sleep(seconds) { + return this.msleep(seconds * 1000); + } ++ ++ ++ goBackInTime(n, timeDuration) { ++ // Note that we are starting from the first ms of the current timeDuration ++ // eg. If we go back by one day we are subtracting (24*60*60*1000) ms from the start ms of today ++ return moment().startOf(timeDuration).subtract(n, timeDuration).format('x'); ++ } ++ ++ goForwardInTime(n, timeDuration) { ++ return moment().startOf(timeDuration).add(n, timeDuration).format('x'); ++ } ++ + } + + const time = new Time();","As a first argument to these function, please pass the date that should go forward/backward. Also please clarify what is ""n"" (possible values, unit) and what is timeDuration (possible values, unit, as from your code it seems to be ""day"", ""hours"", etc. but from your example it seems to be milliseconds)." +1274,"@@ -71,7 +71,11 @@ class AppModule(appModuleHandler.AppModule): + ui.message(_(""No track playing"")) + return elapsedAndTotalTime + +- def script_reportRemainingTime(self,gesture): ++ def script_reportRemainingTime(self, gesture): ++ import config ++ from languageHandler import setLanguage ++ lang = config.conf[""general""][""language""] ++ setLanguage(lang) + elapsedTime, totalTime = self.getElapsedAndTotalIfPlaying() + if elapsedTime is None or totalTime is None: + # Translators: Reported if the remaining time can not be calculated in Foobar2000","Are you sure you really need this code here? that script will be certainly run in NVDA's main thread, and core would have already called setLanguage." +1275,"@@ -276,7 +276,7 @@ var _ = Describe(""Application deployment in edge_core Testing"", func() { + It(""TC_TEST_APP_DEPLOYMENT_16: Test application deployment with container network configuration as port mapping"", func() { + //Generate the random string and assign as a UID + UID = ""deployment-app-"" + edge.GetRandomString(10) +- port := []v1.ContainerPort{{HostPort: 10255, ContainerPort: 10255, Protocol: v1.ProtocolTCP, HostIP: ""127.0.0.1""}} ++ port := []v1.ContainerPort{{HostPort: 10256, ContainerPort: 10256, Protocol: v1.ProtocolTCP, HostIP: ""127.0.0.1""}} + IsAppDeployed := HandleAddAndDeletePods(http.MethodPut, ctx.Cfg.TestManager+AppHandler, UID, []v1.Container{{Name: UID, Image: ctx.Cfg.AppImageUrl[0], Ports: port, ImagePullPolicy: v1.PullIfNotPresent}}, v1.RestartPolicyOnFailure) + Expect(IsAppDeployed).Should(BeTrue()) + CheckPodRunningState(ctx.Cfg.EdgedEndpoint+AppHandler, UID)",why is this changed ? +1276,"@@ -182,8 +182,9 @@ func (l *ActionList) Get(doc Document, fps ...FieldPath) *ActionList { + // mod ""a.b"": 2, then either Update will fail, or it will succeed with the result + // {a: {b: 2}}. + // +-// Update does not modify its doc argument. To obtain the new value of the document, +-// call Get after calling Update. ++// Update does not modify its doc argument, except to set the new revision. To obtain ++// the new value of the document, call Get after calling Update. ++// TODO(jba): test that doc's revision field is updated. + func (l *ActionList) Update(doc Document, mods Mods) *ActionList { + return l.add(&Action{ + kind: driver.Update,","Should this be ""the new revision value""?" +1277,"@@ -13,7 +13,7 @@ + + return [ + 'accepted' => ':attribute må aksepteres.', +- 'accepted_if' => 'The :attribute must be accepted when :other is :value.', ++ 'accepted_if' => 'Dette feltet må aksepteres når :other er :value.', + 'active_url' => ':attribute er ikke en gyldig URL.', + 'after' => ':attribute må være en dato etter :date.', + 'after_or_equal' => ':attribute må være en dato etter eller lik :date.',",You have deleted :attribute +1278,"@@ -1,12 +1,11 @@ + /* +- * Licensed to the Apache Software Foundation (ASF) under one or more +- * contributor license agreements. See the NOTICE file distributed with +- * this work for additional information regarding copyright ownership. +- * The ASF licenses this file to You 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 ++ * Copyright 2017 Huawei Technologies Co., Ltd + * +- * http://www.apache.org/licenses/LICENSE-2.0 ++ * 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,",The license header should be updated to the Apache one. +1279,"@@ -22,6 +22,10 @@ namespace Datadog.Trace.ClrProfiler.IntegrationTests + [Trait(""RunOnWindows"", ""True"")] + public void HttpClient() + { ++ int expectedSpanCount = EnvironmentHelper.IsCoreClr() ? 2 : 1; ++ const string expectedOperationName = ""http.request""; ++ const string expectedServiceName = ""Samples.HttpMessageHandler-http-client""; ++ + int agentPort = TcpPortProvider.GetOpenPort(); + int httpPort = TcpPortProvider.GetOpenPort(); + ",@zacharycmontoya Is there any way to distinguish a `SocketHttpHandler` from another `HttpMessageHandler` request? +1280,"@@ -883,3 +883,17 @@ instr_is_exclusive_store(instr_t *instr) + return (opcode == OP_strex || opcode == OP_strexb || opcode == OP_strexd || + opcode == OP_strexh); + } ++ ++DR_API ++bool ++instr_is_scatter(instr_t *instr) ++{ ++ return false; ++} ++ ++DR_API ++bool ++instr_is_gather(instr_t *instr) ++{ ++ return false; ++}",Not sure about this one -- did you check somehow? +1281,"@@ -157,8 +157,15 @@ module Beaker + @options = @options.merge(env_vars) + + if @options.is_pe? +- @options['pe_ver'] = Beaker::Options::PEVersionScraper.load_pe_version(@options[:pe_dir], @options[:pe_version_file]) +- @options['pe_ver_win'] = Beaker::Options::PEVersionScraper.load_pe_version(@options[:pe_dir], @options[:pe_version_file_win]) ++ @options['HOSTS'].each_key do |name, val| ++ if @options['HOSTS'][name]['platform'] =~ /windows/ ++ @options['HOSTS'][name]['pe_ver_win'] = @options['HOSTS'][name]['pe_ver_win'] || Beaker::Options::PEVersionScraper.load_pe_version( ++ @options['HOSTS'][name][:pe_dir] || @options[:pe_dir], @options[:pe_version_file_win]) ++ else ++ @options['HOSTS'][name]['pe_ver'] = @options['HOSTS'][name]['pe_ver'] || Beaker::Options::PEVersionScraper.load_pe_version( ++ @options['HOSTS'][name][:pe_dir] || @options[:pe_dir], @options[:pe_version_file]) ++ end ++ end + else + @options['puppet_ver'] = @options[:puppet] + @options['facter_ver'] = @options[:facter]",Is there a good reason to keep this at the `pe_ver_win` name now that it's per-host? +1282,"@@ -97,7 +97,9 @@ public class ProductActivity extends BaseActivity { + String[] menuTitles = getResources().getStringArray(R.array.nav_drawer_items_product); + + ProductFragmentPagerAdapter adapterResult = new ProductFragmentPagerAdapter(getSupportFragmentManager()); +- adapterResult.addFragment(new SummaryProductFragment(), menuTitles[0]); ++ SummaryProductFragment summaryProductFragment = new SummaryProductFragment(); ++ ++ adapterResult.addFragment(summaryProductFragment, menuTitles[0]); + adapterResult.addFragment(new IngredientsProductFragment(), menuTitles[1]); + adapterResult.addFragment(new NutritionProductFragment(), menuTitles[2]); + adapterResult.addFragment(new NutritionInfoProductFragment(), menuTitles[3]);","Not in the order of display : Front, Ingredient, Nutrition here (which is the right thing), Actually displayed: Front, Nutrition, Ingredients" +1283,"@@ -119,9 +119,6 @@ type StressInstance struct { + // UID is the instance identifier + // +optional + UID string `json:""uid""` +- // StartTime specifies when the instance starts +- // +optional +- StartTime *metav1.Time `json:""startTime""` + } + + // GetDuration gets the duration of StressChaos",Why delete `StartTime`? This `StartTime` was used to avoid the PID was reused. +1284,"@@ -489,6 +489,10 @@ module Beaker + end + + rescue Exception => teardown_exception ++ if !host.is_pe? ++ dump_puppet_log(host) ++ end ++ + if original_exception + logger.error(""Raised during attempt to teardown with_puppet_running_on: #{teardown_exception}\n---\n"") + raise original_exception","My concern here, is that if the dump_puppet_log also throws then we will lose the data about the teardown_exception." +1285,"@@ -53,10 +53,11 @@ static infer_result call_daal_kernel( + + const std::int64_t dummy_seed = 777; + const auto data_use_in_model = daal_knn::doNotUse; +- daal_knn::Parameter daal_parameter(desc.get_class_count(), +- desc.get_neighbor_count(), +- dummy_seed, +- data_use_in_model); ++ daal_knn::Parameter daal_parameter( ++ dal::detail::integral_cast(desc.get_class_count()), ++ dal::detail::integral_cast(desc.get_neighbor_count()), ++ dal::detail::integral_cast(dummy_seed), ++ data_use_in_model); + + interop::status_to_exception(interop::call_daal_kernel( + ctx,",Should it be `int64_t`? +1286,"@@ -26,10 +26,14 @@ import java.util.concurrent.TimeUnit; + + import com.google.common.base.Stopwatch; + import org.apache.logging.log4j.Logger; ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.concurrent.ExpiringMap; + import org.apache.tuweni.units.bigints.UInt256; + + public class PoWSolver { + ++ private static final long POW_JOB_TTL = 1000 * 60 * 5; // 5 minutes ++ private static final int MAX_OMMER_DEPTH = 8; + private static final Logger LOG = getLogger(); + + public static class PoWSolverJob {",is this value related to something ? +1287,"@@ -23,6 +23,6 @@ namespace Nethermind.TxPool + { + public interface ITxSender + { +- ValueTask SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions); ++ ValueTask<(Keccak?, AddTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions); + } + }","Add names to tuple elements ValueTask<(Keccak? Hash, AddTxResult? AddResult)>, should they both be nullable?" +1288,"@@ -136,6 +136,7 @@ public class Name { + private String toUnderscore(CaseFormat caseFormat) { + List newPieces = new ArrayList<>(); + for (NamePiece namePiece : namePieces) { ++ namePiece = replaceAcronyms(namePiece); + newPieces.add(namePiece.caseFormat.to(caseFormat, namePiece.identifier)); + } + return Joiner.on('_').join(newPieces);",I think it might make more sense to do this in Name.upperCamel; it is the entry point for upper camel strings. +1289,"@@ -53,7 +53,7 @@ public class TypeTest { + assertTrue(type.isArrayType()); + ArrayType arrayType = type.asArrayType(); + final ArrayType[] s = new ArrayType[1]; +- type.ifArrayType(t -> s[0] = t); ++ type.ifArrayType(t -> s[0] = (ArrayType)t); + assertNotNull(s[0]); + } + }",Huh? The point is that a cast isn't necessary +1290,"@@ -35,4 +35,12 @@ const ( + // + // Default is ""true"" + CreateDefaultStorageConfig menv.ENVKey = ""OPENEBS_IO_CREATE_DEFAULT_STORAGE_CONFIG"" ++ ++ // InstallCRD is the environment ++ // variable that flags if maya apiserver should install the CRDs ++ // As the installation moves towards helm 3, the responsibility of installing ++ // CRDs can be pushed to helm. ++ // ++ // Default is ""true"" ++ InstallCRD menv.ENVKey = ""OPENEBS_IO_INSTALL_CRD"" + )",can we name it like `InstallV1Alpha1CRDs` ? +1291,"@@ -79,6 +79,7 @@ const ( + deleteAfterAnnotation = ""hive.openshift.io/delete-after"" + tryInstallOnceAnnotation = ""hive.openshift.io/try-install-once"" + tryUninstallOnceAnnotation = ""hive.openshift.io/try-uninstall-once"" ++ hiveutilCreatedLabel = ""hive.openshift.io/hiveutil-created"" + cloudAWS = ""aws"" + cloudAzure = ""azure"" + cloudGCP = ""gcp""",I need something to match when creating selectorsyncsets so added this label. +1292,"@@ -47,7 +47,9 @@ module RSpec + return nil if line == '-e:1'.freeze + line + rescue SecurityError ++ # :nocov: + nil ++ # :nocov: + end + + # @private","Isn't `nil` the default return value from an empty `rescue` clause? If that's correct, then we could just remove the `nil` line entirely as it doesn't serve a purpose." +1293,"@@ -1,11 +1,14 @@ + # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + # SPDX - License - Identifier: Apache - 2.0 + ++# Purpose ++# This code example demonstrates how to add a cross-origin resource sharing (CORS) ++# configuration containing a single rule to an Amazon Simple Storage Solution (Amazon S3) bucket. ++ ++# snippet-start:[s3.s3_ruby_bucket_cors.rb] ++ + require 'aws-sdk-s3' + +-# Adds a cross-origin resource sharing (CORS) configuration containing +-# a single rule to an Amazon S3 bucket. +-# + # Prerequisites: + # + # - An Amazon S3 bucket.",Simple Storage **Service** +1294,"@@ -471,6 +471,9 @@ func (r *Repository) LoadIndex(ctx context.Context) error { + return err + } + ++ // remove obsolete indexes ++ validIndex.Sub(r.idx.Obsolete()) ++ + // remove index files from the cache which have been removed in the repo + return r.PrepareCache(validIndex) + }",Wouldn't that cause the obsolete indexes to be downloaded over and over again? After all these are still stored in the repository. +1295,"@@ -0,0 +1,19 @@ ++class FeedbackController < ApplicationController ++ # note that index is rendered implicitly as it's just a template ++ ++ def create ++ message = [] ++ [:bug, :context, :expected, :actually, :comments, :satisfaction, :referral].each do |key| ++ if !params[key].blank? ++ message << ""#{key}: #{params[key]}"" ++ end ++ end ++ message = message.join(""\n"") ++ if !message.blank? ++ if current_user ++ message += ""\nuser: #{current_user.email_address}"" ++ end ++ CommunicartMailer.feedback(message).deliver ++ end ++ end ++end",We might want to move this logic to a Plain Old Ruby Object down the road. Not a blocker. +1296,"@@ -1482,7 +1482,9 @@ Blockly.WorkspaceSvg.prototype.updateToolbox = function(tree) { + this.options.languageTree = tree; + this.flyout_.show(tree.childNodes); + } +- this.toolbox_.position(); ++ if (this.toolbox_) { ++ this.toolbox_.position(); ++ } + }; + + /**","move `this.toolbox_.position();` to just after line 1477. Context: the if statement on line 1472 checks whether this is a toolbox with categories, and if so it populates the toolbox. Positioning the toolbox is a reasonable followup to that, and means you don't need an extra if. You may also need to call `this.flyout_.position()` after line 1483, which is the equivalent for the non-category toolbox." +1297,"@@ -364,10 +364,10 @@ namespace pwiz.Skyline.EditUI + var peptideDocNode = tuple.Item2; + HashSet proteins = new HashSet(); + var peptideGroupDocNode = PeptideGroupDocNodes.First(g => ReferenceEquals(g.PeptideGroup, peptideGroup)); +- List proteinsForSequence; +- if (sequenceProteinsDict.TryGetValue(peptideDocNode.Peptide.Target.Sequence, out proteinsForSequence)) ++ // ReSharper disable once ConditionIsAlwaysTrueOrFalse ++ if (peptideGroupDocNode != null) + { +- if (peptideGroupDocNode != null) ++ if (sequenceProteinsDict.TryGetValue(peptideDocNode.Peptide.Target.Sequence, out var proteinsForSequence)) + { + foreach (var protein in proteinsForSequence) + {","Should the function above be .FirstOrDefault() instead? Otherwise, why check for null and tell ReSharper to ignore the fact that it can never be null?" +1298,"@@ -17,7 +17,9 @@ var fetch = {}, + _ = require('underscore'), + crypto = require('crypto'), + usage = require('./usage.js'), +- plugins = require('../../../plugins/pluginManager.js'); ++ STATUS_MAP = require('../jobs/job').STATUS_MAP, ++ plugins = require('../../../plugins/pluginManager.js'), ++ countlyDb = plugins.dbConnection(); + + /** + * Prefetch event data, either by provided key or first event in the list and output result to browser","Let's not create new connection, but rather user `common.db` one" +1299,"@@ -0,0 +1,11 @@ ++module OpenGraphHelper ++ def open_graph_tags ++ tag('meta', property: 'og:image', content: image_url('learn/learn-ralph.png')) ++ end ++ ++ private ++ ++ def image_url(filename) ++ URI.join(root_url, image_path(filename)) ++ end ++end",Can this use asset_path rather than defining an image_url helper? +1300,"@@ -0,0 +1,19 @@ ++import { always } from 'ramda'; ++ ++/** ++ * A function that returns empty string. ++ * ++ * @func stubString ++ * @memberOf RA ++ * @since {@link https://char0n.github.io/ramda-adjunct/2.1.0|v2.1.0} ++ * @category Function ++ * @sig ... -> '' ++ * @return {''} ++ * @example ++ * ++ * RA.stubString(); //=> '' ++ * RA.stubString(1, 2, 3); //=> '' ++ */ ++const stubString = always(''); ++ ++export default stubString;",Hindley-Milner signatures don't use literal types. They explusively use types. It's deal with that +1301,"@@ -61,3 +61,11 @@ type Priority struct { + PolicyPriority float64 + RulePriority int32 + } ++ ++// OFPolicyRule groups all configurations that the openflow module needs to install flow for PolicyRule. ++type OFPolicyRule struct { ++ OfID uint32 ++ OfRule *PolicyRule ++ NpName string ++ NpNamespace string ++}","Could we just extend PolicyRule with more fields? It was originally designed as the struct required by openflow client, nested structs seem not helping. And for the name of the fields, initialism should be uppercase, OFID and NPName doesn't look good, then maybe FlowID, PolicyName.." +1302,"@@ -485,9 +485,13 @@ class Functions + + // bcmath + 'bcscale', +- ++ + // json + 'json_last_error', ++ ++ // opcache ++ 'opcache_compile_file', 'opcache_get_configuration', 'opcache_get_status', ++ 'opcache_invalidate', 'opcache_is_script_cached', 'opcache_reset', + ]; + + if (\in_array(strtolower($function_id), $impure_functions, true)) {","I really dislike this alignment approach, as it makes identifying individual functions quite hard, but I kept consistent with the previous style. Since no sorting was evident, I pushed it to the end of the block. Meanwhile, is this supposed to be tested or meaningfully testable somehow?" +1303,"@@ -127,6 +127,10 @@ class StepDelegatingExecutor(Executor): + running_steps[step.key] = step + + last_check_step_health_time = pendulum.now(""UTC"") ++ ++ # Order of events is important here. During an interation, we call handle_event, then get_steps_to_execute, ++ # then is_complete. get_steps_to_execute updates the state of ActiveExecution, and without it ++ # is_complete can return true when we're just between steps. + while not active_execution.is_complete: + + if active_execution.check_for_interrupts():",Could also consider modifying the ActiveExecution... +1304,"@@ -1522,3 +1522,19 @@ def get_iterating_dictionary_name( + return node.iter.as_string() + + return None ++ ++ ++def get_subscript_const_value(node: astroid.Subscript) -> astroid.Const: ++ """""" ++ Returns the value (subscript.slice) of a Subscript node, ++ also supports python <3.9 windows where node.slice might be an Index ++ node ++ """""" ++ value = node.slice ++ if isinstance(value, astroid.Index): ++ value = value.value ++ inferred = safe_infer(value) ++ if not isinstance(inferred, astroid.Const): ++ raise ValueError(""Subscript.slice cannot be inferred as an astroid.Const"") ++ ++ return inferred",Does it make sense to change that to a custom error instead of `ValueError`? +1305,"@@ -259,7 +259,7 @@ func (vm *VM) ApplyTipSetMessages(blocks []interpreter.BlockMessagesInfo, head b + + // Pay block reward. + // Dragons: missing final protocol design on if/how to determine the nominal power +- rewardMessage := makeBlockRewardMessage(blk.Miner, minerPenaltyTotal, minerGasRewardTotal, blk.TicketCount) ++ rewardMessage := makeBlockRewardMessage(blk.Miner, minerPenaltyTotal, minerGasRewardTotal, 1) + if _, err := vm.applyImplicitMessage(rewardMessage, rnd); err != nil { + return nil, err + }",I guess this will need to change soon. +1306,"@@ -37,10 +37,9 @@ import ( + // The header directive goes second so that headers + // can be manipulated before doing redirects. + var directiveOrder = []string{ ++ ""map"", + ""root"", +- + ""header"", +- + ""redir"", + ""rewrite"", + ",Restore this spacing - not sure why it has to be removed? +1307,"@@ -16,7 +16,10 @@ + + // clang-format off + // Dont't remove `format off`, it prevent reordering of win-includes. +-#define _POSIX_C_SOURCE 200112L // For stat from stat/stat.h and fseeko() (POSIX extensions). ++ ++# define _XOPEN_SOURCE 700L ++# define _POSIX_C_SOURCE 200809L ++ + #ifdef _WIN32 + # ifndef WIN32_LEAN_AND_MEAN + # define WIN32_LEAN_AND_MEAN","These defines cause issues in base.h leading to failing android builds. Locale independency is now set in multiple spots, in cmake and in base.h. The base.h uses feature test macros wrong. Feature test macros can be used to indicate that a feature should be made available. They do not guarantee that it is available. On the cmake side this is done by the check symbol macros (similar to what autoconf does). On the android side not. I would suggest removing this from base.h and define locale independent in gradle. It is available since android 21 I believe. Is there a way in gradle to set locale independent only if android api >= 21?" +1308,"@@ -504,7 +504,7 @@ SubPlan GoPlanner::mToNStepsPlan(SubPlan& startVidPlan) { + } + + const auto& projectInput = +- (joinInput || joinDst) ? loopBody->outputVar() : sampleLimit->outputVar(); ++ (loopBody != getDst) ? loopBody->outputVar() : sampleLimit->outputVar(); + loopBody = Project::make(qctx, loopBody, goCtx_->yieldExpr); + loopBody->setInputVar(projectInput); + loopBody->setColNames(std::move(goCtx_->colNames));",Why not delete these codes? +1309,"@@ -112,7 +112,7 @@ bool StorageServer::start() { + metaClient_ = std::make_unique(ioThreadPool_, + metaAddrs_, + options); +- if (!metaClient_->waitForMetadReady()) { ++ if (!metaClient_->waitForMetadReady(FLAGS_meta_client_retry_times)) { + LOG(ERROR) << ""waitForMetadReady error!""; + return false; + }","If pull message failed after some reties, we should ensure the storaged exit, otherwise it has risk to loss data." +1310,"@@ -7,7 +7,7 @@ + import pytest + import random + import datatable as dt +-from datatable import f, stype, ltype ++from datatable import f, stype, ltype, first, count + from tests import list_equals + + ",looks like you don't need to import first and count here anymore +1311,"@@ -2511,6 +2511,18 @@ func (e *historyEngineImpl) NotifyNewTransferTasks( + } + } + ++func (e *historyEngineImpl) NotifyNewVisibilityTasks( ++ tasks []persistence.Task, ++) { ++ ++ if len(tasks) > 0 { ++ // TODO (alex): add visibility processor ++ // task := tasks[0] ++ // clusterName := e.clusterMetadata.ClusterNameForFailoverVersion(task.GetVersion()) ++ // e.visibilityProcessor.NotifyNewTask(clusterName, tasks) ++ } ++} ++ + func (e *historyEngineImpl) NotifyNewReplicationTasks( + tasks []persistence.Task, + ) {","FYI, visibility task processing is local only, meaning pushing something to local ES cluster / local archival endpoint" +1312,"@@ -36,6 +36,8 @@ import org.springframework.http.HttpMethod; + import org.springframework.http.ResponseEntity; + import org.springframework.web.client.RestTemplate; + ++import com.netflix.config.DynamicPropertyFactory; ++ + public class SpringmvcClient { + private static RestTemplate templateUrlWithServiceName = new CseRestTemplate(); + ",This import can be removed. +1313,"@@ -48,6 +48,10 @@ func ParseResource(s string, resParser ResourceParser) (resARN Resource, err err + return nil, InvalidARNError{ARN: a, Reason: ""service is not supported""} + } + ++ if strings.HasPrefix(a.Region, ""fips-"") || strings.HasSuffix(a.Region, ""-fips"") { ++ return nil, InvalidARNError{ARN: a, Reason: ""FIPS region not allowed in ARN""} ++ } ++ + if len(a.Resource) == 0 { + return nil, InvalidARNError{ARN: a, Reason: ""resource not set""} + }","1. Nit: We can have a general helper to identify if a region is pseudo region. We might already have one somewhere. 2. Does any type of ARN support FIPS? If not, we may just move this check in arn package?" +1314,"@@ -8,10 +8,14 @@ name of the service that is used by Boto 3. + This factory is used by the make_stubber fixture found in the set of common fixtures. + """""" + +-from test_tools.s3_stubber import S3Stubber + from test_tools.dynamodb_stubber import DynamoStubber ++from test_tools.iam_stubber import IamStubber ++from test_tools.lambda_stubber import LambdaStubber + from test_tools.pinpoint_stubber import PinpointStubber ++from test_tools.s3_stubber import S3Stubber ++from test_tools.s3control_stubber import S3ControlStubber + from test_tools.sqs_stubber import SqsStubber ++from test_tools.sts_stubber import StsStubber + + + class StubberFactoryNotImplemented(Exception):",is this phrase completed in a next line? Or forgot to add... what? +1315,"@@ -0,0 +1,11 @@ ++_base_ = [ ++ '../_base_/models/mask_rcnn_r50_fpn.py', ++ '../_base_/datasets/deepfashion.py', '../_base_/schedules/schedule_1x.py', ++ '../_base_/default_runtime.py' ++] ++model = dict( ++ roi_head=dict( ++ bbox_head=dict(num_classes=15), mask_head=dict(num_classes=15))) ++# runtime settings ++total_epochs = 12 ++workflow = [('train', 5)]","`('train', 5)` and `('train', 1)` are actually the same." +1316,"@@ -205,8 +205,8 @@ func (bt *backpressureTracker) beforeDiskBlockCachePut(blockResources int64) ( + return availableResources + } + +-func (bt *backpressureTracker) getLimitInfo() (used int64, limit int64) { +- return bt.used, bt.limit ++func (bt *backpressureTracker) getLimitInfo() (used int64, limit float64) { ++ return bt.used, bt.currLimit() + } + + type backpressureTrackerStatus struct {",Would it be too complicated to refactor `currLimit` to be an `int64`? +1317,"@@ -23,6 +23,13 @@ module RSpec + def assertions + @assertions ||= 0 + end ++ ++ RSPEC_SKIP_IMPLEMENTATION = ::RSpec::Core::Pending.instance_method(:skip) ++ # Minitest::Assertions has it's own `skip`, we need to make sure ++ # RSpec::Core::Pending#skip is used instead. ++ def skip(*args) ++ RSPEC_SKIP_IMPLEMENTATION.bind(self).call(*args) ++ end + end + end + end",Would it be more performant to just `include ::RSpec::Core::Pending` here? /cc @myronmarston +1318,"@@ -92,6 +92,10 @@ type IoChaosSpec struct { + // IoChaosStatus defines the observed state of IoChaos + type IoChaosStatus struct { + ChaosStatus `json:"",inline""` ++ ++ // Instances always specifies podnetworkchaos generation or empty ++ // +optional ++ Instances map[string]int64 `json:""instances,omitempty""` + } + + func (obj *IoChaos) GetSelectorSpecs() map[string]interface{} {",Should be podiochaos? +1319,"@@ -35,6 +35,10 @@ import api + import guiHelper + import winVersion + ++# Temporary: #8599: add cp65001 codec ++# #7105: upgrading to python 3 should fix this issue. See https://bugs.python.org/issue13216 ++codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None) ++ + try: + import updateCheck + except RuntimeError:","Is the `codecs.register(lambda name: None)` gracefully handled by codecs? The lambda is expected to return a tuple of functions (encoder, decoder, stream_reader, stream_writer) (or a CodecInfo object), according to the docs. I've only checked python's built-in help, though." +1320,"@@ -154,6 +154,18 @@ namespace OpenTelemetry.Metrics + { + var metricStreamConfig = metricStreamConfigs[i]; + var metricStreamName = metricStreamConfig?.Name ?? instrument.Name; ++ ++ if (!MeterProviderBuilderSdk.IsValidInstrumentName(metricStreamName)) ++ { ++ OpenTelemetrySdkEventSource.Log.MetricInstrumentIgnored( ++ metricStreamName, ++ instrument.Meter.Name, ++ ""Metric name is invalid."", ++ ""The name must comply with the OpenTelemetry specification.""); ++ ++ continue; ++ } ++ + if (this.metricStreamNames.ContainsKey(metricStreamName)) + { + // TODO: Log that instrument is ignored","in this case, it could be either instrument name or the view name, which could be invalid. might be better if we can offer very specific message. (not blocking this, we can add this as a follow up,if needed)" +1321,"@@ -1654,9 +1654,10 @@ class TargetLocator { + * when the driver has changed focus to the specified window. + */ + window(nameOrHandle) { ++ let paramName = this.driver_.getExecutor().w3c ? 'handle' : 'name'; + return this.driver_.schedule( + new command.Command(command.Name.SWITCH_TO_WINDOW). +- setParameter('name', nameOrHandle), ++ setParameter(paramName, nameOrHandle), + 'WebDriver.switchTo().window(' + nameOrHandle + ')'); + } + ",I'd rather just send the parameter twice than break encapsulation here. There's already precedence with webelement IDs +1322,"@@ -0,0 +1,5 @@ ++_base_ = '../cascade_rcnn/cascade_mask_rcnn_r50_fpn_20e_coco.py' ++model = dict( ++ pretrained= # NOQA ++ 'https://shanghuagao.oss-cn-beijing.aliyuncs.com/res2net/res2net101_v1b_26w_4s_mmdetv2-f0a600f9.pth', # NOQA ++ backbone=dict(type='Res2Net', depth=101, scale=4, base_width=26))",You may put 'open-mmlab://res2net101_v1d_26w_4s' here. MMCV will be updated later. +1323,"@@ -17,3 +17,12 @@ + */ + + export const STORE_NAME = 'modules/pagespeed-insights'; ++ ++// Form ID for PageSpeed widget. ++export const FORM_DASH_WIDGET = 'pagespeedWidget'; ++// Report strategies. ++export const STRATEGY_MOBILE = 'mobile'; ++export const STRATEGY_DESKTOP = 'desktop'; ++// Report data sources. ++export const DATA_SRC_LAB = 'data_lab'; ++export const DATA_SRC_FIELD = 'data_field';","May be worth making this more specific, to avoid potential conflicts, maybe `pagespeedDashboardWidget`? Or `webVitalsDashboardWidget`?" +1324,"@@ -151,7 +151,7 @@ module.exports = class AwsS3Multipart extends Plugin { + const onError = (err) => { + this.uppy.log(err) + this.uppy.emit('upload-error', file, err) +- err.message = `Failed because: ${err.message}` ++ err.message = `${err.message}` + + queuedRequest.done() + this.resetUploaderReferences(file.id)",I guess this assignment is now redundant? +1325,"@@ -218,7 +218,9 @@ func (s *Server) handleSingleRPC(ctx context.Context, req *RPCReq) *RPCRes { + return backendRes + } + +- backendRes, err = s.backendGroups[group].Forward(ctx, req) ++ // NOTE: We call into the specific backend here to ensure that the RPCRes is synchronized with the blockNum. ++ var blockNum uint64 ++ backendRes, blockNum, err = s.backendGroups[group].Forward(ctx, req) + if err != nil { + log.Error( + ""error forwarding RPC request"",",See above note re: blockNum synchronization. +1326,"@@ -10,8 +10,10 @@ import ( + ""time"" + + ""github.com/andres-erbsen/clock"" ++ ""github.com/cenkalti/backoff/v3"" + observer ""github.com/imkira/go-observer"" + ""github.com/spiffe/spire/pkg/agent/client"" ++ spire_backoff ""github.com/spiffe/spire/pkg/agent/common/backoff"" + ""github.com/spiffe/spire/pkg/agent/manager/cache"" + ""github.com/spiffe/spire/pkg/agent/svid"" + ""github.com/spiffe/spire/pkg/common/bundleutil""",wonder if we could avoid doing named imports if we type aliased `backoff.Backoff` in the `.../agent/common/backoff` package? +1327,"@@ -44,7 +44,6 @@ + #include ""disassemble.h"" + #include ""instr.h"" + #include ""instr_create.h"" +- + #include ""codec.h"" + + ",Or maybe put into alphabetical order with the other #includes. +1328,"@@ -235,8 +235,11 @@ func watchConfigFile(filename, adapterName string) { + return false + } + ++ ticker := time.NewTicker(1 * time.Second) ++ defer ticker.Stop() ++ + // begin poller +- for range time.Tick(1 * time.Second) { ++ for range ticker.C { + // get the file info + info, err := os.Stat(filename) + if err != nil {",This runs the entire duration of the program; this change is not needed. +1329,"@@ -20,6 +20,10 @@ export class TouchScroll extends BasePlugin { + return PLUGIN_PRIORITY; + } + ++ static get ALWAYS_UPDATE() { ++ return true; ++ } ++ + constructor(hotInstance) { + super(hotInstance); + ","I don't feel well about the `ALWAYS_UPDATE` option   sounds like a workaround. I can imagine that some of the plugins want to observe all options. Maybe, in that case, we can reuse the `CONFIG_KEYS` that would return an empty array for observing all settings and `false` for disabling observing at all? I just thinking aloud - Like `CONFIG_KEYS` sounds reasonable. We could support and maintain it in the future, even after implementing the ""observability"" to the MetaManager then `ALWAYS_UPDATE` ... I don't know :)" +1330,"@@ -34,6 +34,11 @@ + * by asynch interrupt. + */ + ++/* clang-format off */ ++/* XXX: clang-format incorrectly detected a tab difference at ""clang-format on"" ++ * below. This is why ""clang-format off"" has been moved outside the ifdef until ++ * bug is fixed. ++ */ + #ifndef ASM_CODE_ONLY /* C code */ + # include ""configure.h"" + # ifndef UNIX","A ""tab difference""? As in, there are tab characters somewhere? This disabling of clang-format for all the code here seems like overkill. Are you sure there's not some other solution? I don't really understand the problem though. Do you mean clang-format-diff?" +1331,"@@ -31,12 +31,7 @@ import org.openqa.selenium.grid.sessionmap.SessionMap; + import org.openqa.selenium.grid.sessionmap.local.LocalSessionMap; + import org.openqa.selenium.netty.server.NettyServer; + import org.openqa.selenium.remote.SessionId; +-import org.openqa.selenium.remote.http.HttpClient; +-import org.openqa.selenium.remote.http.HttpHandler; +-import org.openqa.selenium.remote.http.HttpRequest; +-import org.openqa.selenium.remote.http.HttpResponse; +-import org.openqa.selenium.remote.http.TextMessage; +-import org.openqa.selenium.remote.http.WebSocket; ++import org.openqa.selenium.remote.http.*; + import org.openqa.selenium.remote.tracing.DefaultTestTracer; + import org.openqa.selenium.remote.tracing.Tracer; + ",Could you please leave the explicit imports? +1332,"@@ -265,6 +265,9 @@ public abstract class GapicInterfaceConfig implements InterfaceConfig { + } + List methodConfigs = new ArrayList<>(); + for (MethodConfigProto methodConfigProto : interfaceConfigProto.getMethodsList()) { ++ if (methodConfigMap.get(methodConfigProto.getName()) == null) { ++ continue; ++ } + methodConfigs.add(methodConfigMap.get(methodConfigProto.getName())); + } + return methodConfigs;",Can we check for containsKey here? +1333,"@@ -35,9 +35,14 @@ import ( + ""golang.org/x/tools/go/types/typeutil"" + ) + ++const usage = ""usage: wire [gen] [PKG] | wire show [...] | wire check [...]"" ++ + func main() { + var err error + switch { ++ case len(os.Args) == 2 && (os.Args[1] == ""help"" || os.Args[1] == ""-h"" || os.Args[1] == ""-help"" || os.Args[1] == ""--help""): ++ fmt.Fprintln(os.Stderr, usage) ++ os.Exit(2) + case len(os.Args) == 1 || len(os.Args) == 2 && os.Args[1] == ""gen"": + err = generate(""."") + case len(os.Args) == 2 && os.Args[1] == ""show"":",Exit successfully. We served the help the user wanted. +1334,"@@ -15,13 +15,13 @@ import ( + // RepoRoot is the root of the Please repository + var RepoRoot string + +-// initialWorkingDir is the directory we began in. Early on we chdir() to the repo root but for ++// InitialWorkingDir is the directory we began in. Early on we chdir() to the repo root but for + // some things we need to remember this. +-var initialWorkingDir string ++var InitialWorkingDir string + +-// initialPackage is the initial subdir of the working directory, ie. what package did we start in. +-// This is similar but not identical to initialWorkingDir. +-var initialPackage string ++// InitialPackagePath is the initial subdir of the working directory, ie. what package did we start in. ++// This is similar but not identical to InitialWorkingDir. ++var InitialPackagePath string + + // usingBazelWorkspace is true if we detected a Bazel WORKSPACE file to find our repo root. + var usingBazelWorkspace bool",Had to rename this because `InitialPackage()` already existed. +1335,"@@ -19,4 +19,15 @@ module IntegrationSpecHelper + } + ) + end ++ ++ def with_18f_procurement_env_variables(setup_vars=nil) ++ old_approver_email = ENV['GSA18F_APPROVER_EMAIL'] ++ old_purchaser_email = ENV['GSA18F_PURCHASER_EMAIL'] ++ ++ ENV['GSA18F_APPROVER_EMAIL'] = 'test_approver@some-dot-gov.gov' ++ ENV['GSA18F_PURCHASER_EMAIL'] = 'test_purchaser@some-dot-gov.gov' ++ yield ++ ENV['GSA18F_APPROVER_EMAIL'] = old_approver_email ++ ENV['GSA18F_PURCHASER_EMAIL'] = old_purchaser_email ++ end + end",Can we put this in a different helper? +1336,"@@ -603,6 +603,9 @@ insert_push_all_registers(dcontext_t *dcontext, clean_call_info_t *cci, + DR_REG_LIST_LENGTH_ARM, DR_REG_LIST_ARM)); + } + dstack_offs += 15 * XSP_SZ; ++ ++ /* Make dstack_offs 8-byte algined, as we only accounted for 31 4-byte slots */ ++ dstack_offs += XSP_SZ; + ASSERT(cci->skip_save_flags || + cci->num_simd_skip != 0 || + cci->num_regs_skip != 0 ||","I'm not sure where your 31 comes from? I see 15 here and 2 above for pc and flags, for 17 total beyond the SIMD." +1337,"@@ -46,4 +46,10 @@ public class Info extends AbstractApiBean { + public Response getServer() { + return response( req -> ok(systemConfig.getDataverseServer())); + } ++ ++ @GET ++ @Path(""apiTermsOfUse"") ++ public Response getTermsOfUse() { ++ return response( req -> ok(systemConfig.getApiTermsOfUse())); ++ } + }","If you want, you could change this to `allowCors(response` (like in ""version"", above) to allow Cross-Origin Resource Sharing. I'm sort of wondering what's returned if no API terms of use are set." +1338,"@@ -1616,4 +1616,9 @@ public class MessageList extends K9Activity implements MessageListFragmentListen + } + } + } ++ ++ @Override ++ public void onConfigurationChanged(Configuration newConfig) { ++ super.onConfigurationChanged(newConfig); ++ } + }",Why do we need to override this if all we're doing is passing it up? +1339,"@@ -356,6 +356,9 @@ void CmpSeabaseDDL::createSeabaseTableLike( + query += keyClause; + } + ++ // send any user CQDs down ++ Lng32 retCode = sendAllControls(FALSE, FALSE, TRUE); ++ + ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, + CmpCommon::context()->sqlSession()->getParentQid()); + ","Just wondering whether it's safe to send all CQDs to the child compiler. As this missing CQD is causing trouble, maybe some other user CQDs that now get sent could also cause the statement to fail? Also, if I have a table with a nullable unique column, should I have to set this CQD to create another table like it, or should the CREATE TABLE LIKE work without the CQD?" +1340,"@@ -1,11 +1,16 @@ + import os + ++import packaging.version ++import requests ++ + from ..defines import GCP_CREDS_LOCAL_FILE + from ..module_build_spec import ModuleBuildSpec + from ..utils import connect_sibling_docker_container, network_buildkite_container + from .test_images import publish_test_images, test_image_depends_fn + + SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) ++DAGSTER_FROM_SOURCE = ""current_branch"" ++DAGSTER_EARLIEST_RELEASE = ""0.12.4"" + + + def integration_suite_extra_cmds_fn(version):",EARLIEST_TESTED_RELEASE might be slightly more clear +1341,"@@ -81,7 +81,7 @@ MSG_STATE_CONFIDENCE = 2 + # Allow stopping after the first semicolon/hash encountered, + # so that an option can be continued with the reasons + # why it is active or disabled. +-OPTION_RGX = re.compile(r""\s*#.*\bpylint:\s*([^;#]+)[;#]{0,1}"") ++OPTION_RGX = re.compile(r'.*#\s*pylint:\s*([^;#]+)[;#]?.*') + + # The line/node distinction does not apply to fatal errors and reports. + _SCOPE_EXEMPT = ""FR""","I think replacing `.*` with `\s*` from after the hash makes sense, but not the rest of the changes." +1342,"@@ -220,6 +220,8 @@ type NetworkPolicyRule struct { + // action “nil” defaults to Allow action, which would be the case for rules created for + // K8s Network Policy. + Action *secv1alpha1.RuleAction `json:""action,omitempty"" protobuf:""bytes,6,opt,name=action,casttype=github.com/vmware-tanzu/antrea/pkg/apis/security/v1alpha1.RuleAction""` ++ // EnableLogging indicates whether or not to generate logs when rules are matched. Default to false. ++ EnableLogging bool `json:""enableLogging"" protobuf:""varint,7,opt,name=enableLogging""` + } + + // Protocol defines network protocols supported for things like container ports.",interesting .. did not know varint tag covered bool as well +1343,"@@ -35,6 +35,11 @@ struct st_duration_stats_t { + struct gkc_summary *process_time; + struct gkc_summary *response_time; + struct gkc_summary *total_time; ++ ++ /** ++ * average event loop latency per worker thread ++ */ ++ H2O_VECTOR(uint64_t) evloop_latency_ms; + }; + + struct st_duration_agg_stats_t {","Could you please elaborate the reason for not using `gkc_summary` like the values above? I ask this, because I assume what we want to collect is a histogram of event loop latency, and we use `gkc_summary` for collecting histograms." +1344,"@@ -187,7 +187,7 @@ Block.prototype.getTransactionHashes = function getTransactionHashes() { + return [Block.Values.NULL_HASH]; + } + for (var t = 0; t < this.txs.length; t++) { +- hashes.push(this.txs[t].hash()); ++ hashes.push(this.txs[t]._getHash()); + } + return hashes; + };",getHash should be a public and without an `_` if used here. +1345,"@@ -71,6 +71,10 @@ func (dv *DefaultBlockValidator) ValidateSemantic(ctx context.Context, child *ty + + // ValidateSyntax validates a single block is correctly formed. + func (dv *DefaultBlockValidator) ValidateSyntax(ctx context.Context, blk *types.Block) error { ++ // hack validate genesisblock ++ if blk.Height == 0 { ++ return nil ++ } + now := uint64(dv.Now().Unix()) + if uint64(blk.Timestamp) > now { + return fmt.Errorf(""block %s with timestamp %d generate in future at time %d"", blk.Cid().String(), blk.Timestamp, now)",Unrelated to these changes -- we will probably want some special handling for genesis block validation. +1346,"@@ -75,6 +75,10 @@ type diskBlockCacheSetter interface { + MakeDiskBlockCacheIfNotExists() error + } + ++type diskBlockCacheFractionSetter interface { ++ SetDiskBlockCacheFraction(float64) ++} ++ + type clockGetter interface { + Clock() Clock + }","This is probably overkill since we don't actually need to pass this specific interface anywhere, but I don't mind it!" +1347,"@@ -56,6 +56,8 @@ func (d *Driver) AddPeer(ctx context.Context, addr swarm.Address) error { + d.mtx.Unlock() + return nil + } ++ ++ d.receivedPeers[addr.ByteString()] = struct{}{} + d.mtx.Unlock() + + connectedPeers := d.p2pService.Peers()","@janos I moved this back here, to avoid having multiple add peer calls being handled. I think it's either this or a global lock across the whole function. I think this is a better approach, especially since `hive.Broadcast` is blocking . We can remove the map entry on errors if needed. LMKWYT?" +1348,"@@ -0,0 +1,19 @@ ++<% if display_response_actions?(cart, current_user) %> ++
    ++

    ++ <%= link_to ""Approve"", ++ approval_response_path(approver_action: 'approve', ++ cart_id: cart.id, ++ scheme: 'https', ++ user_id: current_user.id, ++ ), class: 'form-button' %> ++ ++ <%= link_to ""Reject"", ++ approval_response_path(approver_action: 'reject', ++ cart_id: cart.id, ++ scheme: 'https', ++ user_id: current_user.id, ++ ), class: 'reject-link' %> ++

    ++
    ++<% end %>",Minor: can we put the conditional outside of the partial? +1349,"@@ -887,7 +887,8 @@ class AsyncSniffer(object): + + if isinstance(offline, Packet): + tempfile_written, offline = _write_to_pcap([offline]) +- elif isinstance(offline, list) and \ ++ elif (isinstance(offline, list) or ++ isinstance(offline, PacketList)) and \ + all(isinstance(elt, Packet) for elt in offline): + tempfile_written, offline = _write_to_pcap(offline) + ",We need to find something more efficient than this. We can probably just check the first element and assume the type list is consistent.. +1350,"@@ -29,6 +29,9 @@ var ( + executions and is good for jobs which need to run frequently. ""Fixed Schedule"" + lets you use a predefined or custom cron schedule and is good for less-frequent + jobs or those which require specific execution schedules.` ++ ++ fmtJobInitTypeHelp = `A %s is a task which can be programmatically run, either on a schedule or via ++service code in response to events.` + ) + + const (","How "" via service code in response to event.""? I don't think we'll get in the no schedule option to the release. We should probably wait for some customer feedback first to make sure we're addressing different event-triggers the best way" +1351,"@@ -65,7 +65,6 @@ PER_YIELD = 1024 + + def generate_model_handle(): + """"""Generate random model handle. +- + Returns: + str: random bytes for handle + """"""",Please move unrelated formatting changes to their own PR (same with the resources.py file). +1352,"@@ -2171,6 +2171,7 @@ class CommandDispatcher: + + window = self._tabbed_browser.window() + if window.isFullScreen(): +- window.showNormal() ++ window.setWindowState(window._state_before_fullscreen & ~Qt.WindowFullScreen) + else: ++ window._state_before_fullscreen = window.windowState() + window.showFullScreen()",Make this a public attribute (remove the leading `_`) if you want to access it from the outside. +1353,"@@ -116,7 +116,7 @@ define(['layoutManager', 'browser', 'actionsheet', 'css!./emby-select', 'registe + inputId++; + } + +- if (!browser.firefox) { ++ if (browser) { + this.classList.add('emby-select-withcolor'); + + if (layoutManager.tv) {",this conditional is useless now so it should be removed +1354,"@@ -262,8 +262,8 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length, + auto vecofstructs = monster->testarrayofsortedstruct(); + if (vecofstructs) { // not filled in monster_test.bfbs + for (size_t i = 0; i < vecofstructs->size()-1; i++) { +- auto left = vecofstructs->Get(i); +- auto right = vecofstructs->Get(i+1); ++ auto left = vecofstructs->Get(static_cast(i)); ++ auto right = vecofstructs->Get(static_cast(i+1)); + TEST_EQ(true, (left->KeyCompareLessThan(right))); + } + TEST_NOTNULL(vecofstructs->LookupByKey(3));","`vecofstructs->size()` already returns a `uoffset_t`. So if you just change the type of `i`, you don't need any casts." +1355,"@@ -197,7 +197,14 @@ public abstract class GapicProductConfig implements ProductConfig { + } + + // Toggle on/off proto annotations parsing. +- ProtoParser protoParser = new ProtoParser(getDefaultLanguageFeatureConfig(language, null)); ++ ProtoParser protoParser; ++ // TODO(andrealin): Expose command-line option for toggling proto annotations parsing. ++ if (configProto == null) { ++ // By default, enable proto annotations parsing when no GAPIC config is given. ++ protoParser = new ProtoParser(true); ++ } else { ++ protoParser = new ProtoParser(getDefaultLanguageFeatureConfig(language, null)); ++ } + if (configProto == null) { + configProto = ConfigProto.getDefaultInstance(); + }","Nit: Maybe merge this with the configProto check on line 208? Don't feel that strongly though, please keep separate if you prefer." +1356,"@@ -138,7 +138,7 @@ describe.skip('Buffering Proxy', function() { + if (die) { + request.connection.destroy(); + } else { +- if (doc.ismaster) { ++ if (doc.ismaster || doc.hello) { + request.reply(primary[currentIsMasterIndex]); + } else if (doc.insert) { + request.reply({ ok: 1, n: 1 });","I know we already did this in 4.0 so carry on, but I'm facepalming here we should've made an overrided setMessageHandler that sets ismaster to true when hello is present. Esp in 4.0 where we already have some overrides written. We can keep going here and maybe open a ticket to some effect of that solution" +1357,"@@ -7,6 +7,10 @@ + <%= json_api_link_tag %> + <% end %> + ++<% content_for(:skip_links) do -%> ++ Skip to first result ++<% end %> ++ + <% content_for(:container_header) do -%> +

    <%= t('blacklight.search.header') %>

    + ","I believe we could use `link_to` here (although not super important). Also, we should internationalize this value. I'm not 100% sure what our process is for adding new UI strings these days (e.g. skip the specs that will fail if we add a new key to only one language, use Google Translate to translate the value for us, some other option)." +1358,"@@ -1323,11 +1323,9 @@ VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalD + instance_data->instance_dispatch_table.GetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, pPropertyCount, pProperties); + + lock.lock(); +- if (result == VK_SUCCESS) { +- if (pProperties) { +- for (uint32_t i = 0; i < *pPropertyCount; ++i) { +- CreateObject(physicalDevice, pProperties[i].display, kVulkanObjectTypeDisplayKHR, nullptr); +- } ++ if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pProperties) { ++ for (uint32_t i = 0; i < *pPropertyCount; ++i) { ++ CreateObject(physicalDevice, pProperties[i].display, kVulkanObjectTypeDisplayKHR, nullptr); + } + } + lock.unlock();",This was already in vkGetPhysicalDeviceDisplayProperties2KHR... +1359,"@@ -498,3 +498,7 @@ type tasksStopper interface { + type serviceLinkedRoleCreator interface { + CreateECSServiceLinkedRole() error + } ++ ++type dockerEngineValidator interface { ++ IsDockerEngineRunning() (string, error) ++}","nit: I'd expect a public method called IsDockerEngineRunning to return a boolean yes/no, not the error message. Can we change either the return value or the name? Something like `CallDockerEngine`" +1360,"@@ -322,12 +322,12 @@ def define_model(model_name, dbengine, model_seed): + cai_resource_name = Column(String(4096)) + cai_resource_type = Column(String(512)) + full_name = Column(String(2048), nullable=False) +- type_name = Column(get_string_by_dialect(dbengine.dialect.name, 512), ++ type_name = Column(get_string_by_dialect(dbengine.dialect.name, 700), + primary_key=True) + parent_type_name = Column( +- get_string_by_dialect(dbengine.dialect.name, 512), ++ get_string_by_dialect(dbengine.dialect.name, 700), + ForeignKey('{}.type_name'.format(resources_tablename))) +- name = Column(String(256), nullable=False) ++ name = Column(String(1024), nullable=False) + type = Column(String(128), nullable=False) + policy_update_counter = Column(Integer, default=0) + display_name = Column(String(256), default='')","If i remembered correctly, type_name is '{RESOURCE_TYPE}/{RESOURCE_NAME}', if type_name is 700 max then name cannot exceed that size" +1361,"@@ -20,6 +20,13 @@ def GetSizePrefix(buf, offset): + """"""Extract the size prefix from a buffer."""""" + return encode.Get(packer.int32, buf, offset) + ++def GetBufferIdentifier(buf, offset, size_prefixed = False): ++ """"""Extract the file_identifier from a buffer"""""" ++ offset+=(number_types.UOffsetTFlags.bytewidth if size_prefixed else 0) + number_types.UOffsetTFlags.bytewidth # offset sizeof(root table offset) + sizeof(size prefix) if present ++ return buf[offset:offset+encode.FILE_IDENTIFIER_LENGTH] ++def BufferHasIdentifier(buf, offset, file_identifier, size_prefixed = False): ++ return GetBufferIdentifier(buf, offset, size_prefixed)==file_identifier ++ + def RemoveSizePrefix(buf, offset): + """""" + Create a slice of a size-prefixed buffer that has","When calling functions with keyword arguments: please provide the arguments as keyword arguments, not positional arguments." +1362,"@@ -41,7 +41,7 @@ class BasicResBlock(nn.Module): + out_channels, + kernel_size=1, + bias=False, +- activation=None, ++ act_cfg=None, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg) + ","We may follow the argument order: conv_cfg, norm_cfg, act_cfg." +1363,"@@ -60,6 +60,19 @@ module Selenium + + class << self + def chrome(opts = {}) ++ define_method(:options) { @capabilities[:chrome_options] ||= {} } ++ define_method(""options="") { |value| @capabilities[:chrome_options] = value } ++ define_method(""profile="") do |profile| ++ profile_json = profile.as_json ++ options['args'] ||= [] ++ if options['args'].none? { |arg| arg =~ /user-data-dir/ } ++ options['args'] << ""--user-data-dir=#{profile_json[:directory]}"" ++ end ++ options['extensions'] = profile_json[:extensions] ++ end ++ alias_method :chrome_options, :options ++ alias_method :chrome_options=, :options= ++ + new({ + browser_name: 'chrome', + javascript_enabled: true,",`options['binary'] = WebDriver::Chrome.path` if set? +1364,"@@ -5,6 +5,7 @@ + */ + + #include ++#include + #include + #include + #include ",folly library should be put on the top. +1365,"@@ -35,6 +35,7 @@ let CAMEL_REG = /-?(?=[A-Z])/g; + function setProperty(dom, name, value, oldValue, isSvg) { + let v; + if (name==='class' || name==='className') name = isSvg ? 'class' : 'className'; ++ const ns = isSvg && (name !== (name = name.replace(/^xlink:?/, ''))); + + if (name==='style') { + ","Do we have to restrict this to SVG elements? I think setting namespaced attributes on normal dom elements (while not as common) is still valid, so perhaps we can save some bytes by removing the `isSvg` check?" +1366,"@@ -134,7 +134,7 @@ class DataProvider { + * @returns {boolean} + */ + _isHiddenRow(row) { +- return this.hot.hasHook('hiddenRow') && this.hot.runHooks('hiddenRow', row); ++ return this.hot.rowIndexMapper.isHidden(this.hot.toPhysicalRow(row)); + } + + /**",Please add it to the `REMOVED_HOOKS` constant. +1367,"@@ -1,7 +1,9 @@ + describe('fieldset', function () { + 'use strict'; + var fixture = document.getElementById('fixture'); ++ var shadowSupport = axe.testUtils.shadowSupport; + var fixtureSetup = axe.testUtils.fixtureSetup; ++ + var checkContext = { + _data: null, + data: function (d) {","This variable needs `.v1` at the end of it, or the tests below need it. There are some test failures as a result" +1368,"@@ -25,6 +25,12 @@ class AccountsController < ApplicationController + render json: Chart.new(@account).commits_by_language(params[:scope]) + end + ++ def label_as_spammer ++ @account = Account.find_by(id: params[:id]) ++ Account::Access.new(@account).spam! ++ render template: 'accounts/disabled' ++ end ++ + private + + def account",Is this access protected so that only admins can access this route? +1369,"@@ -328,7 +328,7 @@ void wlr_output_layout_closest_point(struct wlr_output_layout *layout, + return; + } + +- double min_x = DBL_MAX, min_y = DBL_MAX, min_distance = DBL_MAX; ++ double min_x = 0, min_y = 0, min_distance = DBL_MAX; + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &layout->outputs, link) { + if (reference != NULL && reference != l_output->output) {","What happens if the minimum x coord is > 0? This will incorrectly set it as zero, right?" +1370,"@@ -1637,6 +1637,11 @@ func (o *consumer) processNextMsgReq(_ *subscription, c *client, _, reply string + return + } + ++ if o.maxp > 0 && batchSize > o.maxp { ++ sendErr(409, ""Exceeded MaxAckPending"") ++ return ++ } ++ + // In case we have to queue up this request. + wr := waitingRequest{client: c, reply: reply, n: batchSize, noWait: noWait, expires: expires} + ",I think you want to look at current pending + batchSize and if that is > o.maxp no? +1371,"@@ -189,7 +189,7 @@ func (h *Harness) testSpan(tracerFactory func() trace.Tracer) { + span.AddEventWithTimestamp(context.Background(), time.Now(), ""test event"") + }, + ""#SetStatus"": func(span trace.Span) { +- span.SetStatus(codes.Internal, ""internal"") ++ span.SetStatus(codes.Ok, ""internal"") + }, + ""#SetName"": func(span trace.Span) { + span.SetName(""new name"")",Should this be `codes.Error`? `codes.Internal` was an error status before. +1372,"@@ -26,6 +26,11 @@ class AccountsController < ApplicationController + @projects, @logos = @account.project_core.used + @twitter_detail = TwitterDetail.new(@account) + page_context[:page_header] = 'accounts/show/header' ++ respond_to do |format| ++ format.html ++ format.xml ++ format.json ++ end + end + + def me",I don't think you need these lines. +1373,"@@ -195,7 +195,7 @@ type tlfJournal struct { + // Invariant: this tlfJournal acquires exactly + // blockJournal.getStoredBytes() and + // blockJournal.getStoredFiles() until shutdown. +- DiskLimiter DiskLimiter ++ diskLimiter DiskLimiter + + // All the channels below are used as simple on/off + // signals. They're buffered for one object, and all sends are","You didn't mean to export this, right?" +1374,"@@ -3,7 +3,7 @@ + + # Purpose: + # sns-ruby-example-show-topics.rb demonstrates how to list Amazon Simple Notification Services (SNS) topics using +-# the AWS SDK for JavaScript (v3). ++# the AWS SDK for Ruby. + + # Inputs: + # - REGION",Simple Notification **Service** (singular) +1375,"@@ -313,6 +313,7 @@ type client struct { + replayMutex sync.RWMutex + nodeConfig *config.NodeConfig + networkConfig *config.NetworkConfig ++ egressConfig *config.EgressConfig + gatewayOFPort uint32 + // ovsDatapathType is the type of the datapath used by the bridge. + ovsDatapathType ovsconfig.OVSDatapathType",Do we still need this? +1376,"@@ -108,9 +108,6 @@ public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod { + final Transaction privateMarkerTransaction = + createPrivateMarkerTransaction(privateTransaction, user); + +- LOG.error(""CHEESE""); +- LOG.error(privateMarkerTransaction.getHash()); +- + return transactionPool + .addLocalTransaction(privateMarkerTransaction) + .either(",We do have a disconnect between the privateMarkerTransactionFactory.getSender() call and the createPrivateMarkerTransaction() call. When the plugin receives the call to create the PMT it does not know what the sender was returned by the other call. At a minimum we need to pass in the sender to the second call. I would prefer that the plugin does the locking if that is necessary. If you are using random keys you don't have to lock! Besu could signal to the plugin when a PMT was un- or successfully added to the pool using a callback. Callback could be null if this is not needed. The plugin would have to be able to get the nonce for a certain key from besu. What do you think? +1377,"@@ -217,7 +217,7 @@ import 'css!./imageeditor'; + reload(context, null, focusContext); + }, function () { + import('alert').then(({default: alert}) => { +- alert(globalize.translate('DefaultErrorMessage')); ++ alert(globalize.translate('MessageDefaultError')); + }); + }); + }",This is a bit inconsistent with the `ErrorStartHourGreaterThanEnd` in the previous file. Wouldn't `ErrorDefault``fit better here? +1378,"@@ -35,12 +35,13 @@ import ( + ""antrea.io/antrea/pkg/features"" + ) + +-func skipIfNetworkPolicyStatsDisabled(tb testing.TB, data *TestData) { +- skipIfFeatureDisabled(tb, data, features.NetworkPolicyStats, true, true) ++func skipIfNetworkPolicyStatsDisabled(tb testing.TB) { ++ skipIfFeatureDisabled(tb, features.NetworkPolicyStats, true, true) + } + +-func TestNetworkPolicyStats(t *testing.T) { +- skipIfNotIPv4Cluster(t) ++// TestNetworkPolicy is the top-level test which contains all subtests for ++// NetworkPolicy related test cases so they can share setup, teardown. ++func TestNetworkPolicy(t *testing.T) { + skipIfHasWindowsNodes(t) + + data, err := setupTest(t)",I think it will revert the change @antoninbas did on purpose 05eee251c9c53400277def576f92d614ca234898 +1379,"@@ -614,6 +614,8 @@ func (m *bpfEndpointManager) attachDataIfaceProgram(ifaceName string, polDirecti + epType := tc.EpTypeHost + if ifaceName == ""tunl0"" { + epType = tc.EpTypeTunnel ++ } else if ifaceName == ""wireguard.cali"" { ++ epType = tc.EpTypeWireguard + } + ap := m.calculateTCAttachPoint(epType, polDirection, ifaceName) + ap.HostIP = m.hostIP",nit: a switch perhaps? +1380,"@@ -14,7 +14,7 @@ + + + <%= render_page_title %> +- 'xml', :only_path => false) %>"" title=""<%= application_name%>"" type=""application/opensearchdescription+xml"" rel=""search""/> ++ <%= opensearch_description_tag application_name, opensearch_catalog_path(:format => 'xml', :only_path => false) %> + <%= favicon_link_tag asset_path('favicon.ico') %> + <%= stylesheet_link_tag ""application"" %> + <%= javascript_include_tag ""application"" %>",Would it make sense for `opensearch_description_tag` to have default values for the title and href attributes? +1381,"@@ -281,7 +281,7 @@ func (j journalMDOps) getRange( + []ImmutableRootMetadata, error) { + // Grab the range from the journal first. + jirmds, err := j.getRangeFromJournal(ctx, id, bid, mStatus, start, stop) +- if err != nil { ++ if err != nil && err != errTLFJournalDisabled { + return nil, err + } + ",Just noticed this while debugging -- it's unlikely to be causing issues in practice. +1382,"@@ -75,7 +75,7 @@ describe( 'setting up the Analytics module with no existing account and no exist + await expect( page ).toClick( '.googlesitekit-analytics__select-country' ); + await expect( page ).toClick( '.mdc-menu-surface--open li', { text: /united kingdom/i } ); + +- await expect( page ).toMatchElement( 'p', { text: /need to give Site Kit permission to create an Analytics account/i } ); ++ await expect( page ).toMatchElement( 'p', { text: /need to give Site Kit permission to create an Analytics account/i, timeout: 750 } ); + + await Promise.all( [ + page.waitForNavigation(), // User is sent directly to OAuth.",That seems unrelated - did that fix a random test failure you noticed while working on this issue? +1383,"@@ -98,8 +98,11 @@ public abstract class BaseMetastoreTableOperations implements TableOperations { + LOG.info(""Nothing to commit.""); + return; + } ++ TableMetadata updated = (base != null && base.file() != null) ? ++ metadata.addPreviousMetadata(base.file().location(), base.lastUpdatedMillis()) : metadata; + +- doCommit(base, metadata); ++ doCommit(base, updated); ++ deleteRemovedMetadata(updated); + requestRefresh(); + } + ","This kind of concern should be handled in the `TableMetadata` update methods. This is similar to `metadata.rollbackTo`, which not only sets the current version, but also updates the table history. I think that all of those methods should add the current object's `file.location()` to the previous metadata location list, if it is non-null. That way, the caller never needs to remember to update it." +1384,"@@ -82,3 +82,18 @@ def flip_tensor(src_tensor, flip_direction): + else: + out_tensor = torch.flip(src_tensor, [2, 3]) + return out_tensor ++ ++ ++def collect_mlvl_tensor_single(mlvl_tensors, batch_id, detach=True): ++ assert isinstance(mlvl_tensors, (list, tuple)) ++ num_levels = len(mlvl_tensors) ++ ++ if detach: ++ mlvl_tensor_list = [ ++ mlvl_tensors[i][batch_id].detach() for i in range(num_levels) ++ ] ++ else: ++ mlvl_tensor_list = [ ++ mlvl_tensors[i][batch_id] for i in range(num_levels) ++ ] ++ return mlvl_tensor_list",We need to know why all the tensors are detached in `get_bboxed`. +1385,"@@ -309,3 +309,13 @@ class Foo: + + def method(self): + print(self.__class__.__ham) ++ ++ ++class TypeSelfCallInMethod: ++ """"""Regression test for issue 5569"""""" ++ @classmethod ++ def b(cls) -> None: ++ cls.__a = '' # [unused-private-member] ++ ++ def a(self): ++ return type(self).__a",Unrelated but shouldn't this raise `attribute-defined-outside-init`? +1386,"@@ -24,7 +24,7 @@ class Service(service.ChromiumService): + """""" + + def __init__(self, executable_path, port=0, service_args=None, +- log_path=None, env=None): ++ log_path=None, env=None, create_no_window=False): + """""" + Creates a new instance of the Service + ","I would rather no have this as a `kwarg` as it encourages ""growth"" which lead to an unweildy constructor in other classes. Let's add a method or property to take care of this instead as I think it's usage is going to be quite low." +1387,"@@ -98,8 +98,7 @@ class Phase < ActiveRecord::Base + # TODO: Move this to Plan model as `num_answered_questions(phase=nil)` + # Returns the number of answered question for the phase. + def num_answered_questions(plan) +- return 0 if plan.nil? +- sections.to_a.sum { |s| s.num_answered_questions(plan) } ++ plan&.num_answered_questions.to_i + end + + # Returns the number of questions for a phase. Note, this method becomes useful",You just changed my life :) I grew very attached to this safe nav approach when working with Groovy years ago `obj?.method`. Glad to see its now a part of Ruby! +1388,"@@ -23,9 +23,10 @@ +
    + <%= f.label :published, raw(""#{f.check_box :published, as: :check_boxes, 'data-toggle': 'tooltip', title: _(""Check this box when you are ready for this guidance to appear on user's plans."")} #{_('Published?')}"") %> +
    +- +- <%= f.submit _('Save'), name: ""edit_guidance_submit"", class: ""btn btn-primary"" %> +- <%= link_to _('Cancel'), admin_index_guidance_path, class: ""btn btn-primary"", role: 'button' %> ++
    ++ <%= f.submit _('Save'), name: ""edit_guidance_submit"", class: ""btn btn-primary"" %> ++ <%= link_to _('Cancel'), admin_index_guidance_path, class: ""btn btn-primary"", role: 'button' %> ++
    + <%end%> +
    + ",do you mean 'clearfix' class? +1389,"@@ -391,6 +391,7 @@ MongoClient.connect = function(url, options, callback) { + * Starts a new session on the server + * + * @param {SessionOptions} [options] optional settings for a driver session ++ * @param {boolean} [options.causalConsistency=true] Enables or disables causal consistency for the session. + * @return {ClientSession} the newly established session + */ + MongoClient.prototype.startSession = function(options) {",`causalConsistency` is already defined on `SessionOptions`. We do not need to duplicate it here. +1390,"@@ -46,9 +46,7 @@ import java.lang.reflect.Method; + + import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +-import static org.mockito.ArgumentMatchers.any; +-import static org.mockito.ArgumentMatchers.anyString; +-import static org.mockito.ArgumentMatchers.eq; ++import static org.mockito.ArgumentMatchers.*; + import static org.mockito.Mockito.*; + + /**",This should not be included since there are no code changes. +1391,"@@ -56,6 +56,18 @@ func askCredentials(c *context.Context, status int, text string) { + + func HTTPContexter() macaron.Handler { + return func(c *context.Context) { ++ if len(setting.HTTP.AccessControlAllowOrigin) > 0 { ++ // Set CORS headers for browser-based git clients ++ c.Resp.Header().Set(""Access-Control-Allow-Origin"", setting.HTTP.AccessControlAllowOrigin) ++ c.Resp.Header().Set(""Access-Control-Allow-Headers"", ""Content-Type, Authorization"") ++ ++ // Handle preflight OPTIONS request ++ if c.Req.Method == ""OPTIONS"" { ++ c.Status(http.StatusOK) ++ return ++ } ++ } ++ + ownerName := c.Params("":username"") + repoName := strings.TrimSuffix(c.Params("":reponame""), "".git"") + repoName = strings.TrimSuffix(repoName, "".wiki"")","If all we need just response 200, then we could use `c.Status(http.StatusOK)` here." +1392,"@@ -683,6 +683,11 @@ func loadConfigFromDatastore( + Name: ""node."" + hostname, + Namespace: """", + }, """") ++ n, err := client.Get(ctx, model.ResourceKey{ ++ Kind: apiv2.KindNode, ++ Name: hostname, ++ Namespace: """", ++ }, """") + if _, ok := err.(errors2.ErrorResourceDoesNotExist); err != nil && !ok { + return + }",Should be checking for error here +1393,"@@ -431,7 +431,7 @@ class Form extends WidgetBase + $this->fields = []; + } + +- $this->allTabs->outside = new FormTabs(FormTabs::SECTION_OUTSIDE, $this->config); ++ $this->allTabs->outside = new FormTabs(FormTabs::SECTION_OUTSIDE, (array)$this->config); + $this->addFields($this->fields); + + /*",Put a space between `(array)` and `$this` and I'll merge it +1394,"@@ -0,0 +1,6 @@ ++package runtime ++ ++// Stack is a stub, not implemented ++func Stack(buf []byte, all bool) int { ++ return 0 ++}","You could add this to stack.go, which has similar functions (to avoid yet another small file). None of these are likely to be implemented considering what TinyGo is designed for." +1395,"@@ -0,0 +1,13 @@ ++package com.fsck.k9.notification; ++ ++ ++class NotificationHolder { ++ public final int notificationId; ++ public final NotificationContent content; ++ ++ ++ public NotificationHolder(int notificationId, NotificationContent content) { ++ this.notificationId = notificationId; ++ this.content = content; ++ } ++}","the class names `NotificationHolder` and `NotificationsHolder` are fairly difficult to quickly tell apart, particularly since they are often used close to each other" +1396,"@@ -23,10 +23,7 @@ + */ + package net.runelite.client.plugins.freezetimers; + +-import java.util.ArrayList; +-import java.util.HashMap; +-import java.util.List; +-import java.util.Map; ++import java.util.*; + import javax.inject.Singleton; + import lombok.extern.slf4j.Slf4j; + import net.runelite.api.Actor;",Avoid wildcard imports +1397,"@@ -71,7 +71,7 @@ type ( + GetContractState(hash.PKHash, hash.Hash32B) (hash.Hash32B, error) + SetContractState(hash.PKHash, hash.Hash32B, hash.Hash32B) error + // Candidate pool +- candidates() (uint64, []*Candidate) ++ Candidates() (uint64, []*Candidate) + CandidatesByHeight(uint64) ([]*Candidate, error) + } + ",Need to do this to unblock mockgen. The interface method needs to be public to be visible in another package. The right fix is to delete this test only interface method +1398,"@@ -101,6 +101,13 @@ module.exports = function(url, options, callback) { + record = record[0].join(''); + const parsedRecord = qs.parse(record); + const items = Object.keys(parsedRecord); ++ if ( ++ Object.keys(items) ++ .map(k => k.toLowerCase()) ++ .indexOf('loadbalanced') !== -1 ++ ) { ++ return callback(new MongoParseError('Load balancer mode requires driver version 4+')); ++ } + if (items.some(item => item !== 'authSource' && item !== 'replicaSet')) { + return callback( + new MongoParseError('Text record must only set `authSource` or `replicaSet`')",same question here as I have on the other file regarding doing this check here vs L112 vs not at all +1399,"@@ -1,3 +1,5 @@ ++// +build !openbsd ++ + package fuse + + import (",Adding `// +build !windows` (as a separate line) will do the same for Windows. So while you are at it we might add it as well. +1400,"@@ -35,7 +35,6 @@ class BZAObject(dict): + self.token = None + self.log = logging.getLogger(self.__class__.__name__) + self.http_session = requests.Session() +- self.http_request = self.http_session.request + + # copy infrastructure from prototype + if isinstance(proto, BZAObject):","this is used as important way of mocking for unit tests, FYI" +1401,"@@ -156,6 +156,7 @@ if not config.style_17: + options.Points = Options('plot', show_frame=True) + + options.Histogram = Options('style', line_color='black', fill_color=Cycle()) ++options.Distribution = Options('style', muted_alpha=0.2) + options.ErrorBars = Options('style', color='black') + options.Spread = Options('style', color=Cycle(), alpha=0.6, line_color='black') + options.Bars = Options('style', color=Cycle(), line_color='black', width=0.8)","Sorry, should have been clearer, I meant adding this to the ``Histogram`` options one line above." +1402,"@@ -566,7 +566,7 @@ namespace pwiz.SkylineTest + // Bad terminus + AssertEx.DeserializeError(""""); + // Bad formula +- AssertEx.DeserializeError(""""); ++ AssertEx.DeserializeError(""""); + // Terminal label without amino acid + AssertEx.DeserializeError(""""); + // Formula and labeled atoms","Just ignorance on my part, but what is the significance of the change from C23NHe2 to C23NHx2?" +1403,"@@ -486,6 +486,12 @@ class histogram(Operation): + bin_range = param.NumericTuple(default=None, length=2, doc="""""" + Specifies the range within which to compute the bins."""""") + ++ bins = param.ClassSelector(default=None, class_=(np.ndarray, list), doc="""""" ++ An explicit set of bin edges."""""") ++ ++ cumulative = param.Boolean(default=False, doc="""""" ++ Whether to compute the cumulative histogram"""""") ++ + dimension = param.String(default=None, doc="""""" + Along which dimension of the Element to compute the histogram."""""") + ",What about tuples or pandas series? Do we want to support lots of different types or force a single type? +1404,"@@ -294,10 +294,6 @@ public class ZkStateReader implements SolrCloseable { + log.debug(""Loading collection config from: [{}]"", path); + + try { +- if (zkClient.exists(path, true) == false) { +- log.warn(""No collection found at path {}."", path); +- throw new KeeperException.NoNodeException(""No collection found at path: "" + path); +- } + byte[] data = zkClient.getData(path, null, null, true); + if (data == null) { + log.warn(""No config data found at path {}."", path);","Small thing, without the check above this will throw a NoNodeException if the path doesn't exist. Maybe this can be wrapped in a try/catch just for the NoNodeException, so that the more user-friendly message used above can be thrown instead: `throw new KeeperException.NoNodeException(""No collection found at path: "" + path);` Just a thought, I'm not even sure it's worth it." +1405,"@@ -17,7 +17,7 @@ class Project < ActiveRecord::Base + validates :url_name, presence: true, length: 1..60, allow_nil: false, uniqueness: { case_sensitive: false } + validates :description, length: 0..800, allow_nil: true # , if: proc { |p| p.validate_url_name_and_desc == 'true' } + validates_each :url, :download_url, allow_blank: true do |record, field, value| +- record.errors.add(field, I18n.t(:not_a_valid_url)) unless value.valid_http_url? ++ record.errors.add(field, I18n.t(:not_a_valid_url)) unless value.blank? || value.valid_http_url? + end + before_validation :clean_strings_and_urls + after_save :update_organzation_project_count","I don't know why this worked before, but we should be explicit on not verifying that a blank string (allowed as a way to remove a url/download_url) is a valid url as it is not." +1406,"@@ -212,8 +212,7 @@ module Bolt + + return unless !stdout.empty? && stdout.to_i < 3 + +- msg = ""Detected PowerShell 2 on controller. PowerShell 2 is deprecated and ""\ +- ""support will be removed in Bolt 3.0."" ++ msg = ""Detected PowerShell 2 on controller. PowerShell 2 is unsupported."" + Bolt::Logger.deprecation_warning(""PowerShell 2 controller"", msg) + end + end","Do we want to raise an error here instead of warning? Or would it be better to just see if Bolt happens to succeed, and let it fail on it's own if it fails? I'd lean towards raising an error, but that's different from ""removing support""." +1407,"@@ -44,7 +44,12 @@ module Bolt + + # Returns options this transport supports + def self.options +- raise NotImplementedError, ""self.options() must be implemented by the transport class"" ++ raise NotImplementedError, ++ ""self.options() or self.filter_options(unfiltered) must be implemented by the transport class"" ++ end ++ ++ def self.filter_options(unfiltered) ++ unfiltered.select { |k| options.include?(k) } + end + + def self.validate(_options)",This is kind of confusing with the other `filter_options`. +1408,"@@ -160,7 +160,12 @@ func (fs *KBFSOpsStandard) DeleteFavorite(ctx context.Context, + return fs.opsByFav[fav] + }() + if ops != nil { +- return ops.deleteFromFavorites(ctx, fs.favs) ++ err := ops.deleteFromFavorites(ctx, fs.favs) ++ if _, ok := err.(OpsCantHandleFavorite); !ok { ++ return err ++ } ++ // If the ops couldn't handle the delete, fall through to ++ // going directly via Favorites. + } + + if isLoggedIn {",Could the `deleteFromFavorites` happen when `head == nil` because it's not initialized yet somehow but not because TLF doesn't exist? I was concerned if this would make it possible in any way to have favorites seemingly deleted on a device while it's not actually happened on server. +1409,"@@ -457,7 +457,7 @@ void CmpSeabaseDDL::dropSeabaseSchema(StmtDDLDropSchema * dropSchemaNode) + + bool isVolatile = (memcmp(schName.data(),""VOLATILE_SCHEMA"",strlen(""VOLATILE_SCHEMA"")) == 0); + int32_t length = 0; +- int32_t rowCount = 0; ++ Int64 rowCount = 0; + bool someObjectsCouldNotBeDropped = false; + char errorObjs[1010]; + Queue * objectsQueue = NULL;","It doesn't look like this particular ""rowCount"" variable is used anywhere. I suppose we could delete it. The code change is harmless though." +1410,"@@ -380,6 +380,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + + status, _ := s.serveHTTP(w, r) + ++ if status == 204 { ++ w.WriteHeader(http.StatusNoContent) ++ } ++ + // Fallback error response in case error handling wasn't chained in + if status >= 400 { + DefaultErrorFunc(w, r, status)","Hmm, probably we should instead write whatever `status` is returned instead of coding a special case." +1411,"@@ -128,6 +128,10 @@ func parsedRuleToProtoRule(in *ParsedRule) *proto.Rule { + } + } + ++ if in.HTTPMatch != nil { ++ out.HttpMatch = &proto.HTTPMatch{Methods: in.HTTPMatch.Methods} ++ } ++ + // Fill in the ICMP fields. We can't follow the pattern and make a + // convertICMP() function because we can't name the return type of the + // function (it's private to the protobuf package).","Could using the pointer-to-struct approach here cause confusion later? We've had several problems of that kind in the past. What does it mean if the struct is non-nil but its fields are nil? Is that even allowed? (libcalico-go question) Are there any validation requirements for this new rule addition; should it only be allowed if `Protocol == TCP`, for example?" +1412,"@@ -11,6 +11,7 @@ class User < ActiveRecord::Base + + has_many :approvals + has_many :observations ++ has_many :observers, through: :observers, source: :user + has_many :comments + + # we do not use rolify gem (e.g.) but declare relationship like any other.",why this recursive relationship definition? +1413,"@@ -40,7 +40,8 @@ type Procedure struct { + // HandlerSpec specifiying which handler and rpc type. + HandlerSpec HandlerSpec + +- // Encoding of the handler, for introspection. ++ // Encoding of the handler, optional, used for introspection, and used for ++ // routing if present. + Encoding Encoding + + // Signature of the handler, for introspection. This should be a snippet of","More sentence, less list please. > Encoding of the handler. This field is optional. We don't need to mention exactly what it's used for because that list can expand (as it has already in this change)." +1414,"@@ -66,6 +66,10 @@ + // are included because they call NewRangeReader.) + // - NewWriter, from creation until the call to Close. + // ++// It also collects the following metrics: ++// - gocloud.dev/blob/bytes_read: the total number of bytes read, by provider. ++// - gocloud.dev/blob/bytes_written: the total number of bytes written, by provider. ++// + // To enable trace collection in your application, see ""Configure Exporter"" at + // https://opencensus.io/quickstart/go/tracing. + // To enable metric collection in your application, see ""Exporting stats"" at","Not part of this PR, but should the section above say what the name of the metric is for each method?" +1415,"@@ -75,13 +75,13 @@ namespace OpenTelemetry.Exporter + + case MetricType.LongGauge: + { +- // TODOs ++ valueDisplay = (metric as IGaugeMetric).LastValue.Value.ToString(); + break; + } + + case MetricType.DoubleGauge: + { +- // TODOs ++ valueDisplay = (metric as IGaugeMetric).LastValue.Value.ToString(); + break; + } + ","there are changes that are upcoming to this section. For now, this works (to demo the usage of Gauge), and the changes to this section are coming as separate PRs." +1416,"@@ -95,7 +95,7 @@ func (t *Terminal) run(ctx context.Context) { + for { + select { + case <-ctx.Done(): +- if IsProcessBackground() { ++ if IsProcessBackground(t.fd) { + // ignore all messages, do nothing, we are in the background process group + continue + }",This is equivalent to stdout. Why not just replace stdin with stdout in `IsProcessBackground`? +1417,"@@ -61,7 +61,10 @@ void DataMan::add_stream(json p_jmsg) + man->init(p_jmsg); + this->add_next(method, man); + } +- add_man_to_path(""zfp"", method); ++ if (p_jmsg[""compress_method""] != nullptr) ++ { ++ add_man_to_path(p_jmsg[""compress_method""], method); ++ } + } + + void DataMan::flush() { flush_next(); }","Rather than test for nullptr, just treat the pointer as a bool, i.e. `if(p_jmsg[""compress_method""])`" +1418,"@@ -146,6 +146,17 @@ public class LibraryFeaturePanel extends FeaturePanel { ++ final ErrorDialog errorDialog = ErrorDialog.builder() ++ .withMessage(tr(""Creating shortcut to executable outside of a container is not supported"")) ++ .withOwner(getScene().getWindow()) ++ .build(); ++ ++ errorDialog.showAndWait(); ++ }); ++ return; ++ } + final String pathInContainers = executablePath.replace(getContainersPath(), """"); + final String[] split = pathInContainers.split(""/""); + final String engineContainer = split[0];","Can we move the remaining code of this method to a new method? I don't like the `return;` here, we could try to replace it with an `if ... else ...` syntax. What do you think?" +1419,"@@ -0,0 +1,14 @@ ++from kinto.core.events import ResourceChanged ++ ++from .listener import on_resource_changed ++ ++ ++def includeme(config): ++ config.add_api_capability('quotas', ++ description='Quotas Management on Buckets.', ++ url='https://kinto.readthedocs.io') ++ ++ # Listen to every resources (except history) ++ config.add_subscriber(on_resource_changed, ResourceChanged, ++ for_resources=('bucket', 'group', ++ 'collection', 'record'))",nitpick: _and collections_ +1420,"@@ -42,6 +42,8 @@ struct rp_generator_t { + int is_websocket_handshake; + int had_body_error; /* set if an error happened while fetching the body so that we can propagate the error */ + h2o_timer_t send_headers_timeout; ++ unsigned req_done : 1; ++ unsigned res_done : 1; + }; + + struct rp_ws_upgrade_info_t {",I believe these need to be explicitly initialized in `proxy_send_prepare` +1421,"@@ -160,6 +160,7 @@ class TaskProcess(multiprocessing.Process): + # Need to have different random seeds if running in separate processes + random.seed((os.getpid(), time.time())) + ++ t0 = time.time() # Failed task start time + status = FAILED + expl = '' + missing = []",This is unnecessary. The declaration of `t0` on line 179 is still in scope inside the `except` block. +1422,"@@ -1,6 +1,15 @@ + */ + + ++/** ++ * The border color when the client is marked. ++ * It has priority over the rest of beautiful border color properties. ++ * Note that only solid colors are supported. ++ * @beautiful beautiful.border_color_marked ++ * @param color ++ * @see request::border ++ */ ++ + /** + * The fallback border color when the client is floating. + *","The `border_color_`... properties don't support solid colors, not only this one. Maybe `@param solid_color` should be used instead of adding this note to every one of them?" +1423,"@@ -0,0 +1,19 @@ ++module.exports = { ++ roots: [ ++ ""/javascript/grid-ui/src"" ++ ], ++ testMatch: [ ++ ""/javascript/grid-ui/src/tests/**/*.test.tsx"" ++ ], ++ transform: { ++ ""^.+\\.(ts|tsx)$"": ""ts-jest"" ++ }, ++ moduleFileExtensions: [""ts"", ""tsx"", ""js"", ""jsx"", ""json"", ""node""], ++ snapshotSerializers: [""enzyme-to-json/serializer""], ++ setupFilesAfterEnv: [""/setupTests.ts""], ++ testEnvironment: ""jsdom"", ++ moduleNameMapper: { ++ "".+\\.(svg|png|jpg|css)$"": ""identity-obj-proxy"", ++ ""selenium/javascript/grid-ui/(.*)"": ""/$1"" ++ } ++}","We don't need this file, we can use the one that is in the grid-ui directory" +1424,"@@ -48,6 +48,10 @@ public class BazelIgnoreParser { + + try { + for (String path : FileOperationProvider.getInstance().readAllLines(bazelIgnoreFile)) { ++ if (!isEmptyLine(path)) { ++ continue; ++ } ++ + if (path.endsWith(""/"")) { + // .bazelignore allows the ""/"" path suffix, but WorkspacePath doesn't. + path = path.substring(0, path.length() - 1);",FYI: inlined this method in the internal review. +1425,"@@ -17,10 +17,8 @@ import org.junit.Test; + import org.junit.runner.RunWith; + + import java.util.ArrayList; +-import java.util.Arrays; + import java.util.Date; + import java.util.List; +-import java.util.concurrent.CountDownLatch; + import java.util.concurrent.TimeUnit; + + import de.danoeh.antennapod.core.feed.Feed;","Werid, the checksum between this file and the one on branch `develop` is the same not sure why it's showing a diff" +1426,"@@ -47,7 +47,7 @@ namespace OpenTelemetry.Exporter + foreach (var metric in exporter.Metrics) + { + var builder = new PrometheusMetricBuilder() +- .WithName(metric.Name) ++ .WithName(metric.Meter.Name + metric.Name) + .WithDescription(metric.Description); + + switch (metric.MetricType)","Prometheus doesn't have concept of Meter (like OTLP does).. Trying to see if this is a good approach to use the meter name as namespace, to avoid name collisions, when same instrument name is used across multiple instruments, from different Meter." +1427,"@@ -78,10 +78,17 @@ class LibraryCardsController extends AbstractBase + // Connect to the ILS for login drivers: + $catalog = $this->getILS(); + ++ $config = $this->getConfig(); ++ $allowConnectingCards = !empty( ++ $config->Catalog ++ ->auth_based_library_cards ++ ) && ++ ($this->getAuthManager()->getAuthMethod() == 'Shibboleth'); + return $this->createViewModel( + [ + 'libraryCards' => $user->getLibraryCards(), +- 'multipleTargets' => $catalog->checkCapability('getLoginDrivers') ++ 'multipleTargets' => $catalog->checkCapability('getLoginDrivers'), ++ 'allowConnectingCards' => $allowConnectingCards, + ] + ); + }","The formatting of this is a bit strange; I'd suggest collapsing this back to a single line, and moving the `&&` to the beginning of the second line to meet the line length restriction." +1428,"@@ -1791,7 +1791,7 @@ create_and_initialize_module_data(app_pc start, app_pc end, app_pc entry_point, + copy->segments[i].end = os_segments[i].end; + copy->segments[i].prot = os_segments[i].prot; + } +- } else ++ } else if (segments != NULL) + memcpy(copy->segments, segments, num_segments*sizeof(module_segment_data_t)); + copy->timestamp = timestamp; + # ifdef MACOS","One or the other should be non-NULL. If segments is NULL, the alloc above will have size zero, which we do not allow (there's no header): it should assert in debug build. So there should be asserts that one is non-NULL at the top, and if there really needs to be some kind of defensive check down here, it should cover the alloc too." +1429,"@@ -106,7 +106,11 @@ class User < ActiveRecord::Base + + def self.from_oauth_hash(auth_hash) + user_data = auth_hash.extra.raw_info.to_hash +- self.find_or_create_by(email_address: user_data['email']) ++ user = self.for_email(user_data['email']) ++ if user_data['first_name'].present? && user_data['last_name'].present? ++ user.update_attributes(first_name: user_data['first_name'], last_name: user_data['last_name']) ++ end ++ user + end + + def role_on(proposal)",I'm surprised rubocop isn't picking up singe quotes? +1430,"@@ -251,14 +251,7 @@ import ( + var _ time.Duration + var _ strings.Reader + var _ aws.Config +- +-func parseTime(layout, value string) *time.Time { +- t, err := time.Parse(layout, value) +- if err != nil { +- panic(err) +- } +- return &t +-} ++var _, _ = protocol.ParseTime(""unixTimestamp"", ""2016-09-27T15:50Z"") + + `)) + ",Is this line still needed? +1431,"@@ -153,10 +153,8 @@ bool EDPSimple::createSEDPEndpoints() + watt.endpoint.multicastLocatorList = this->mp_PDP->getLocalParticipantProxyData()->m_metatrafficMulticastLocatorList; + //watt.endpoint.remoteLocatorList = m_discovery.initialPeersList; + watt.endpoint.durabilityKind = TRANSIENT_LOCAL; +- watt.times.nackResponseDelay.seconds = 0; +- watt.times.nackResponseDelay.fraction = 0; +- watt.times.initialHeartbeatDelay.seconds = 0; +- watt.times.initialHeartbeatDelay.fraction = 0; ++ watt.times.heartbeatPeriod.seconds = 1; ++ watt.times.heartbeatPeriod.fraction = 0; + if(mp_RTPSParticipant->getRTPSParticipantAttributes().throughputController.bytesPerPeriod != UINT32_MAX && + mp_RTPSParticipant->getRTPSParticipantAttributes().throughputController.periodMillisecs != 0) + watt.mode = ASYNCHRONOUS_WRITER;","Maybe use specific values for all the watt.times fields? Even better, have a const for it at the top of the file?" +1432,"@@ -21,9 +21,10 @@ import inputCore + + #: The directory in which liblouis braille tables are located. + TABLES_DIR = r""louis\tables"" ++PATTERNS_TABLE = os.path.join(TABLES_DIR, ""braille-patterns.cti"") + +-#: The table file names and information. +-TABLES = ( ++#: The braille table file names and information. ++tables = [ + # (fileName, displayName, supportsInput), + # Translators: The name of a braille table displayed in the + # braille settings dialog.","nit: UNICODE_BRAILLE_TABLE or something might be a better name for this. IMO, braille-patterns.cti is a terrible name. This table allows Unicode braille characters to be used anywhere to produce raw dots." +1433,"@@ -104,9 +104,6 @@ type Builder struct { + + // MachineNetwork is the subnet to use for the cluster's machine network. + MachineNetwork string +- +- // SkipMachinePoolGeneration is set to skip generating MachinePool objects +- SkipMachinePoolGeneration bool + } + + // Validate ensures that the builder's fields are logically configured and usable to generate the cluster resources.",Why are we removing the option to skip machine pool generation? +1434,"@@ -0,0 +1,9 @@ ++using System; ++ ++namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http ++{ ++ public interface IHttpStartLineHandler ++ { ++ void OnStartLine(HttpMethod method, HttpVersion version, Span target, Span path, Span query, Span customMethod); ++ } ++}","""Request line"" here too." +1435,"@@ -1292,6 +1292,19 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) + std::vector args; + args.push_back(inst); + args.push_back(this); ++ if (RuleB(Zone, UseZoneController)) { ++ if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)){ ++ if (parse->EventNPC(EVENT_LOOT_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), client, buf, 0, &args) != 0) { ++ lootitem->auto_loot = -1; ++ client->MessageString(Chat::Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name); ++ client->QueuePacket(app); ++ delete inst; ++ return; ++ } ++ } ++ } ++ ++ + if (parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args) != 0) { + lootitem->auto_loot = -1; + client->MessageString(Chat::Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name);",Please remove this. +1436,"@@ -15,6 +15,7 @@ class Organization::Affiliated < Organization::AccountFacts + accounts = @organization.accounts.joins([:person, :positions]) + accounts = accounts.group('accounts.id, people.kudo_position').order('kudo_position nulls last') + accounts.paginate(per_page: limit, page: page) ++ Account.paginate_by_sql(accounts.to_sql, per_page: limit, page: page) + end + + def projects(page = 1, limit = 10)","Weird bug. Combining those joins and group calls was triggering AREL to generate the sql cache inside of will_paginate before the final call. This is a harmless workaround, but hints that will_paginate might becoming seriously deprecated." +1437,"@@ -75,6 +75,12 @@ class Analysis < ActiveRecord::Base + end.compact.join(' AND ') + end + ++ def allowed_tuples ++ [].tap do |tuples| ++ analysis_sloc_sets.each { |analysis_sloc_set| tuples << analysis_sloc_set.allowed_tuples } ++ end.compact.join(' AND ') ++ end ++ + def angle + (Math.atan(hotness_score) * 180 / Math::PI).round(3) + end",This can be simplified as discussed before. +1438,"@@ -1,7 +1,14 @@ + package execute + +-import ""github.com/influxdata/flux"" ++import ( ++ ""github.com/influxdata/flux"" ++ ""github.com/influxdata/flux/execute/table"" ++) + + func NewProcessMsg(tbl flux.Table) ProcessMsg { + return &processMsg{table: tbl} + } ++ ++func NewProcessChunkMsg(chunk table.Chunk) ProcessChunkMsg { ++ return &processChunkMsg{chunk: chunk} ++}",Does `internal` or `test` in the file name actually do anything here? Or is that just to show these functions are only for tests? +1439,"@@ -12,7 +12,7 @@ describe('Transaction deserialization', function() { + vectors_valid.forEach(function(vector) { + if (vector.length > 1) { + var hexa = vector[1]; +- Transaction(hexa).serialize().should.equal(hexa); ++ Transaction(hexa).serialize(true).should.equal(hexa); + index++; + } + });",does this boolean indicate unsafe serialization? +1440,"@@ -332,6 +332,13 @@ class Realm { + */ + static deleteFile(config) {} + ++ /** ++ * Copy bundled Realm files to app's default file folder. ++ * This is not implemented for node.js. ++ * @throws {Error} If an I/O error occured or method is not implemented. ++ */ ++ static copyBundledRealmFiles() {} ++ + /** + * Get a list of subscriptions. THIS METHOD IS IN BETA AND MAY CHANGE IN FUTURE VERSIONS. + * @param {string} name - Optional parameter to query for either a specific name or pattern (using",Maybe rewrite to `Is only implemented for React Native`? (I assume that is the case). +1441,"@@ -246,8 +246,15 @@ public abstract class PageStreamingConfig { + if (pageSizeField == null) { + // TODO: Conform to design doc spec, once approved, for using non-standard paging fields + // (such as max_results for page_size) +- if (language == TargetLanguage.JAVA && transportProtocol == TransportProtocol.HTTP) { +- pageSizeField = methodModel.getInputField(pagingParams.getNameForMaxResults()); ++ if (transportProtocol == TransportProtocol.HTTP) { ++ if (language == TargetLanguage.JAVA) { ++ pageSizeField = methodModel.getInputField(pagingParams.getNameForMaxResults()); ++ } else if (language == TargetLanguage.PHP) { ++ FieldModel resourcesField = ProtoPageStreamingTransformer.getResourcesField(methodModel); ++ if (resourcesField != null && !resourcesField.isMap()) { ++ pageSizeField = methodModel.getInputField(pagingParams.getNameForMaxResults()); ++ } ++ } + } + } + ProtoField responseTokenField =",Do we not need this in Java because Java *is* handling map responses? +1442,"@@ -279,6 +279,14 @@ class Task(object): + except BaseException: + logger.exception(""Error in event callback for %r"", event) + ++ @property ++ def accepted_messages(self): ++ """""" ++ Configures which scheduler messages can be received and returns them. When falsy, this tasks ++ does not accept any message. When True, all messages are accepted. ++ """""" ++ return False ++ + @property + def task_module(self): + ''' Returns what Python module to import to get access to this class. '''","Maybe ""For configuring which scheduler messages can be received.""?" +1443,"@@ -141,7 +141,7 @@ class SyncThumbsCommand extends BaseCommand + } + + //clear entity manager for saving memory +- $this->getMediaManager()->getEntityManager()->clear(); ++ $this->getMediaManager()->getObjectManager()->clear(); + + if ($batchesLimit > 0 && $batchCounter == $batchesLimit) { + break;","It will stop working with orm, so this is not a good fix, Try using some method in a common interface" +1444,"@@ -40,7 +40,11 @@ namespace OpenTelemetry.Collector.Dependencies + { + this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber( + new Dictionary, ListenerHandler>>() +- { { ""HttpHandlerDiagnosticListener"", (t, s) => new HttpHandlerDiagnosticListener(t, s) } }, ++ { ++ { ""HttpHandlerDiagnosticListener"", (t, s) => new HttpHandlerDiagnosticListener(t, s) }, ++ { ""Azure.Clients"", (t, s) => new AzureSdkDiagnosticListener(""Azure.Clients"", t, sampler) }, ++ { ""Azure.Pipeline"", (t, s) => new AzureSdkDiagnosticListener(""Azure.Pipeline"", t, sampler) }, ++ }, + tracer, + x => + {",`s` is not necessarily the same as `sampler` - sampler could be null and this crazy lambda underneath falls back to something. So please use `s` +1445,"@@ -83,9 +83,14 @@ public class PojoOperationGenerator extends AbstractOperationGenerator { + bodyModel = new ModelImpl(); + bodyModel.setType(ModelImpl.OBJECT); + for (ParameterGenerator parameterGenerator : bodyFields) { +- SwaggerUtils.addDefinitions(swagger, parameterGenerator.getGenericType()); ++ parameterGenerator.setHttpParameterType(HttpParameterType.BODY); ++ scanMethodParameter(parameterGenerator); ++ + Property property = ModelConverters.getInstance().readAsProperty(parameterGenerator.getGenericType()); ++ property.setDescription(parameterGenerator.getGeneratedParameter().getDescription()); + bodyModel.addProperty(parameterGenerator.getParameterName(), property); ++ ++ parameterGenerator.setHttpParameterType(null); + } + swagger.addDefinition(simpleRef, bodyModel); + ",This code is a bit confusing. Should HttpParameterType set to the original one or it is always BODY? +1446,"@@ -741,7 +741,7 @@ func (c *Client) reallyExecute(tid int, target *core.BuildTarget, command *pb.Co + return nil, nil, err + } + log.Debug(""Completed remote build action for %s"", target) +- if err := c.verifyActionResult(target, command, digest, response.Result, false, isTest); err != nil { ++ if err := c.verifyActionResult(target, command, digest, response.Result, c.state.Config.Remote.VerifyOutputs && !isTest, isTest); err != nil { + return metadata, response.Result, err + } + c.locallyCacheResults(target, digest, metadata, response.Result)",Why did this change? +1447,"@@ -55,11 +55,14 @@ func (c *client) DescribeTable(ctx context.Context, region string, tableName str + + globalSecondaryIndexes := getGlobalSecondaryIndexes(result.Table.GlobalSecondaryIndexes) + ++ status := newProtoForTableStatus(result.Table.TableStatus) ++ + ret := &dynamodbv1.Table{ + Name: aws.ToString(result.Table.TableName), + Region: region, + GlobalSecondaryIndexes: globalSecondaryIndexes, + ProvisionedThroughput: currentCapacity, ++ Status: status, + } + return ret, nil + }",nit: `status` collides with imported package named `status` +1448,"@@ -584,6 +584,14 @@ func (l *Ledger) trackerEvalVerified(blk bookkeeping.Block, accUpdatesLedger led + return eval(context.Background(), accUpdatesLedger, blk, false, nil, nil) + } + ++// IsWritingCatchpointFile returns true when a catchpoint file is being generated. The function is used by the catchup service so ++// that the memory pressure could be decreased until the catchpoint file writing is complete. ++func (l *Ledger) IsWritingCatchpointFile() bool { ++ l.trackerMu.RLock() ++ defer l.trackerMu.RUnlock() ++ return l.accts.IsWritingCatchpointFile() ++} ++ + // A txlease is a transaction (sender, lease) pair which uniquely specifies a + // transaction lease. + type txlease struct {","""memory pressure could be decreased"" --> ""to avoid memory pressure""" +1449,"@@ -426,8 +426,11 @@ class TestTimescaleListenStore(DatabaseTestCase): + self.assertEqual(count + 1, int(cache.get(user_key, decode=False) or 0)) + + def test_delete_listens(self): +- self._create_test_data(self.testuser_name) +- listens, min_ts, max_ts = self.logstore.fetch_listens(user_name=self.testuser_name, to_ts=1400000300) ++ uid = random.randint(2000, 1 << 31) ++ testuser = db_user.get_or_create(uid, ""user_%d"" % uid) ++ testuser_name = testuser['musicbrainz_id'] ++ self._create_test_data(testuser_name) ++ listens, min_ts, max_ts = self.logstore.fetch_listens(user_name=testuser_name, to_ts=1400000300) + self.assertEqual(len(listens), 5) + self.assertEqual(listens[0].ts_since_epoch, 1400000200) + self.assertEqual(listens[1].ts_since_epoch, 1400000150)",I think it would make sense to fetch the cache values after deleting the listens and making sure they are what we expect. +1450,"@@ -169,6 +169,11 @@ export class CollapsibleColumns extends BasePlugin { + }); + + } else if (Array.isArray(collapsibleColumns)) { ++ ++ this.headerStateManager.mapState(() => { ++ return { collapsible: false }; ++ }); ++ + this.headerStateManager.mergeStateWith(collapsibleColumns); + } + }",I'm thinking about covering this change with the test. Can you do that? +1451,"@@ -41,7 +41,7 @@ var ( + + // NATProviderPinger pings provider and optionally hands off connection to consumer proxy. + type NATProviderPinger interface { +- PingProvider(ip string, providerPort, consumerPort, proxyPort int, stop <-chan struct{}) error ++ PingProvider(ip string, cPorts, pPorts []int, proxyPort int) (*net.UDPConn, error) + } + + // NATPinger is responsible for pinging nat holes",Not sure if it's a good idea to remove stop channel. If user cancels connection how will you stop pinger? +1452,"@@ -373,7 +373,13 @@ func (dg *dockerGoClient) pullImage(image string, authData *apicontainer.Registr + return CannotGetDockerClientError{version: dg.version, err: err} + } + +- authConfig, err := dg.getAuthdata(image, authData) ++ sdkAuthConfig, err := dg.getAuthdata(image, authData) ++ authConfig := docker.AuthConfiguration{ ++ Username: sdkAuthConfig.Username, ++ Password: sdkAuthConfig.Password, ++ Email: sdkAuthConfig.Email, ++ ServerAddress: sdkAuthConfig.ServerAddress, ++ } + if err != nil { + return wrapPullErrorAsNamedError(err) + }",Could you please add a `TODO` here that we won't need `docker.AuthConfiguration` anymore when we migrate to SDK's pull image? +1453,"@@ -31,6 +31,8 @@ namespace Microsoft.DotNet.Build.CloudTestTasks + + public string BlobNamePrefix { get; set; } + ++ public ITaskItem[] BlobNames { get; set; } ++ + public override bool Execute() + { + return ExecuteAsync().GetAwaiter().GetResult();",Is there a scenario were we want to get an arbitrary set of blobs that don't share a common root? +1454,"@@ -22,5 +22,7 @@ describe('Client Side Encryption', function() { + return testContext.setup(this.configuration); + }); + +- generateTopologyTests(testSuites, testContext); ++ generateTopologyTests(testSuites, testContext, spec => { ++ return !spec.description.match(/type=regex/); ++ }); + });",Can you leave a note about why we are skipping regex tests? +1455,"@@ -55,10 +55,15 @@ var initCmd = &cmds.Command{ + if err != nil { + return err + } +- rep, err := repo.CreateRepo(repoDir, newConfig) ++ ++ if err := repo.InitFSRepo(repoDir, newConfig); err != nil { ++ return err ++ } ++ rep, err := repo.OpenFSRepo(repoDir) + if err != nil { + return err + } ++ + // The only error Close can return is that the repo has already been closed + defer rep.Close() // nolint: errcheck + ","This was the only caller of CreateRepo, so I inlined it." +1456,"@@ -109,6 +109,8 @@ type VaultAuth struct { + TokenSecretRef SecretKeySelector `json:""tokenSecretRef,omitempty""` + // This Secret contains a AppRole and Secret + AppRole VaultAppRole `json:""appRole,omitempty""` ++ // Where the authentication path is mounted in Vault. ++ AuthPath string `json:""authPath,omitempty""` + } + + type VaultAppRole struct {","As this is already a child of `auth`, I think we can shorten this to `path`" +1457,"@@ -297,6 +297,14 @@ class UIATextInfo(textInfos.TextInfo): + elif position==textInfos.POSITION_LAST: + self._rangeObj=self.obj.UIATextPattern.documentRange + self.collapse(True) ++ elif position in (textInfos.POSITION_FIRSTVISIBLE, textInfos.POSITION_LASTVISIBLE): ++ try: ++ visiRanges = self.obj.UIATextPattern.GetVisibleRanges() ++ element = 0 if position == textInfos.POSITION_FIRSTVISIBLE else visiRanges.length - 1 ++ self._rangeObj = visiRanges.GetElement(0) ++ except COMError: ++ # Error: FIRST_VISIBLE position not supported by the UIA text pattern. ++ raise NotImplementedError + elif position==textInfos.POSITION_ALL or position==self.obj: + self._rangeObj=self.obj.UIATextPattern.documentRange + elif isinstance(position,UIA) or isinstance(position,UIAHandler.IUIAutomationElement):","This call should use element, not 0 I think." +1458,"@@ -223,6 +223,8 @@ type Options struct { + ChunkSize fs.SizeSuffix `config:""chunk_size""` + NoChunk bool `config:""no_chunk""` + Enc encoder.MultiEncoder `config:""encoding""` ++ FetchUntilEmptyPage bool `config:""fetch_until_empty_page""` ++ PartialPageFetchThreshold int `config:""partial_page_fetch_threshold""` + } + + // Fs represents a remote swift server",This is missing the definition of `fetch_until_empty_page` - it needs to go in the config section above. +1459,"@@ -170,8 +170,8 @@ module Selenium + + def macosx_path + path = ""/Applications/Firefox.app/Contents/MacOS/firefox-bin"" +- path = ""~/Applications/Firefox.app/Contents/MacOS/firefox-bin"" unless File.exist?(path) +- path = Platform.find_binary(""firefox-bin"") unless File.exist?(path) ++ path = ""~/Applications/Firefox.app/Contents/MacOS/firefox-bin"" unless File.exist?(File.expand_path(path)) ++ path = Platform.find_binary(""firefox-bin"") unless File.exist?(File.expand_path?(path)) + + path + end",I don't think this one needs to be changed since the only previous path is already an absolute one. +1460,"@@ -200,7 +200,7 @@ public class BaseExpireSnapshotsSparkAction + } + + private Dataset buildValidFileDF(TableMetadata metadata) { +- Table staticTable = newStaticTable(metadata, this.table.io()); ++ Table staticTable = newStaticTable(metadata, this.table.io(), table.locationProvider()); + return appendTypeString(buildValidDataFileDF(staticTable), DATA_FILE) + .union(appendTypeString(buildManifestFileDF(staticTable), MANIFEST)) + .union(appendTypeString(buildManifestListDF(staticTable), MANIFEST_LIST));",Since we kept the original constructor we might not need this change now. +1461,"@@ -130,6 +130,7 @@ public class HiveTableOperations extends BaseMetastoreTableOperations { + } + + refreshFromMetadataLocation(metadataLocation); ++ LOG.debug(""Refreshed [{}]"", fullName); + } + + @Override","There is already a log in `BaseMetastoreTableOperations` for this. It has the location, but not the table name. Maybe just add table name to that one." +1462,"@@ -21,6 +21,8 @@ import ( + ""net/http"" + ""time"" + ++ ""github.com/pipe-cd/pipe/pkg/filestore/minio"" ++ + jwtgo ""github.com/dgrijalva/jwt-go"" + ""github.com/spf13/cobra"" + ""go.uber.org/zap""",This should be in the last group. +1463,"@@ -106,6 +106,7 @@ namespace Datadog.Trace.Agent + { + // stop retrying + Log.Error(exception, ""An error occurred while sending traces to the agent at {0}"", _tracesEndpoint); ++ _statsd?.Send(); + return false; + } + ","I believe you should either remove this or rename the PR. You can't change the behavior of the tracer (even to fix a bug) in a PR named ""unit test improvements""" +1464,"@@ -0,0 +1,8 @@ ++// +k8s:deepcopy-gen=package,register ++// +k8s:conversion-gen=github.com/munnerz/cert-manager/pkg/apis/certmanager ++// +k8s:openapi-gen=true ++// +k8s:defaulter-gen=TypeMeta ++ ++// Package v1alpha1 is the v1alpha1 version of the API. ++// +groupName=certmanager.k8s.io ++package v1alpha1","I've gone with this group name, however I'm open to suggestions on alternatives!" +1465,"@@ -32,6 +32,7 @@ public class RpcApis { + public static final RpcApi TX_POOL = new RpcApi(""TXPOOL""); + public static final RpcApi TRACE = new RpcApi(""TRACE""); + public static final RpcApi PLUGINS = new RpcApi(""PLUGINS""); ++ public static final RpcApi QUORUM = new RpcApi(""QUORUM""); + + public static final List DEFAULT_JSON_RPC_APIS = Arrays.asList(ETH, NET, WEB3); + ",should this be GOQUORUM +1466,"@@ -49,7 +49,7 @@ type ( + var cpuprofile = flag.String(""cpuprofile"", """", ""write cpu profile to file"") + + // Validate for the byzantine node uses the actual block validator and returns the opposite +-func (v *byzVal) Validate(blk *blockchain.Block, tipHeight uint64, tipHash hash.Hash32B) error { ++func (v *byzVal) Validate(blk *blockchain.Block, tipHeight uint64, tipHash hash.Hash32B, checkCoinbase bool) error { + //err := v.val.Validate(blk, tipHeight, tipHash) + //if err != nil { + // return nil","I think checkCoinbase is not skipping checking coinbase. Instead, true-> checking num(coinbase tx) = 1, false -> checking num(coinbase tx) = 0." +1467,"@@ -24,14 +24,13 @@ import ( + ""github.com/iotexproject/iotex-core/config"" + ""github.com/iotexproject/iotex-core/db"" + ""github.com/iotexproject/iotex-core/state"" +- ""github.com/iotexproject/iotex-core/state/factory"" + ""github.com/iotexproject/iotex-core/test/identityset"" + ""github.com/iotexproject/iotex-core/test/mock/mock_chainmanager"" + ""github.com/iotexproject/iotex-election/test/mock/mock_committee"" + ""github.com/iotexproject/iotex-election/types"" + ) + +-func initConstruct(t *testing.T) (Protocol, context.Context, factory.WorkingSet, *types.ElectionResult) { ++func initConstruct(t *testing.T) (Protocol, context.Context, protocol.StateManager, *types.ElectionResult) { + require := require.New(t) + ctrl := gomock.NewController(t) + defer ctrl.Finish()","same here, move it out" +1468,"@@ -42,11 +42,17 @@ + //@HEADER + */ + ++#ifndef KOKKOS_TOOLS_INDEPENDENT_BUILD + #include + #include ++#endif ++ + #include +-#if defined(KOKKOS_ENABLE_LIBDL) ++#include ++ ++#if defined(KOKKOS_ENABLE_LIBDL) || defined(KOKKOS_TOOLS_INDEPENDENT_BUILD) + #include ++#define KOKKOS_TOOLS_ENABLE_LIBDL + #endif + + #include ",Can you elaborate on why you need different behavior depending on Tools being built independently or not? +1469,"@@ -18,7 +18,8 @@ class AnnotationsController < ApplicationController + guid_save = guidance.present? ? guidance.save : true + + if ex_save && guid_save +- redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully created.') ++ typ = (!ex_save && !guid_save ? 'example answer and guidance' : (!guid_save ? 'guidance' : 'example answer')) ++ redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: success_message(typ, _('created')) + else + @section = @question.section + @phase = @section.phase","because of the above if statement will requires both ex_save and guid_save to be true, this code will always return 'example answer'. This should be revised with `example_answer.present?` and `guidance.present?`" +1470,"@@ -5,6 +5,7 @@ import ( + ""testing"" + + ""github.com/stretchr/testify/assert"" ++ ""golang.org/x/net/context"" + + ""github.com/sonm-io/core/insonmnia/structs"" + pb ""github.com/sonm-io/core/proto""",why not context from stdlib? +1471,"@@ -48,7 +48,7 @@ func GenerateCRC32( + return Checksum{ + Value: checksum, + Version: payloadVersion, +- Flavor: FlavorIEEECRC32OverThriftBinary, ++ Flavor: FlavorIEEECRC32OverProto3Binary, + }, nil + } + ",Just saw this and wasn't able to hold myself from renaming :-). +1472,"@@ -278,9 +278,7 @@ describe('src/Core', () => { + plugins: {}, + totalProgress: 0 + }) +- expect(core.plugins.acquirer[0].mocks.uninstall.mock.calls.length).toEqual( +- 1 +- ) ++ expect(core.plugins[Object.keys(core.plugins)[0]].length).toEqual(0) + }) + + describe('upload hooks', () => {",Can we keep the other assertion too? I think it's helpful to ensure that the uninstall function was called too +1473,"@@ -109,7 +109,7 @@ module RSpec + def warn_if_key_taken(source, key, new_block) + return unless existing_block = example_block_for(source, key) + +- Kernel.warn <<-WARNING.gsub(/^ +\|/, '') ++ RSpec.warn_with <<-WARNING.gsub(/^ +\|/, '') + |WARNING: Shared example group '#{key}' has been previously defined at: + | #{formatted_location existing_block} + |...and you are now defining it at:","`warn_with` prefixes the message with `WARNING:`, right? So this will put `WARNING:` twice. It would be good to verify all the warnings look good after this change, given how easy it is to make a simple mistake like this :(." +1474,"@@ -12,6 +12,19 @@ import ( + ""github.com/filecoin-project/go-filecoin/types"" + ) + ++// MessageTimeOut is the number of tipsets we should receive before timing out messages ++const MessageTimeOut = 6 ++ ++type timedmessage struct { ++ message *types.SignedMessage ++ addedAt uint64 ++} ++ ++// BlockTimer defines a interface to a struct that can give the current block height. ++type BlockTimer interface { ++ BlockHeight() (uint64, error) ++} ++ + // MessagePool keeps an unordered, de-duplicated set of Messages and supports removal by CID. + // By 'de-duplicated' we mean that insertion of a message by cid that already + // exists is a nop. We use a MessagePool to store all messages received by this node","FYI In the message queue I use the term ""stamp"" to refer to the time-like mark associated with each message. It's opaque to the queue/pool and should make no difference if the stamps and age limit were converted to seconds. So this could then become `Stamper` with `CurrentStamp()` method, no reference to ""blocks"" or height etc. The wrapper struct could be `StampedMessage. The interpretation as block height is deferred to the user/constructor that hooks things up, the ""business logic"". This is just an observation, take or ignore as you wish." +1475,"@@ -508,8 +508,13 @@ def remove_xml_preamble(response): + # -------------- + def get_lifecycle(bucket_name): + bucket_name = normalize_bucket_name(bucket_name) ++ exists, code, body = is_bucket_available(bucket_name) ++ if not exists: ++ return requests_response(body, status_code=code) ++ + lifecycle = BUCKET_LIFECYCLE.get(bucket_name) + status_code = 200 ++ + if not lifecycle: + # TODO: check if bucket actually exists + lifecycle = {",Can we remove the `TODO` statement here? (as this is actually fixed in this PR) +1476,"@@ -198,6 +198,7 @@ public class Account implements BaseAccount, StoreConfig { + private SortType mSortType; + private Map mSortAscending = new HashMap(); + private ShowPictures mShowPictures; ++ private DisplayPreference mDisplayPreference; + private boolean mIsSignatureBeforeQuotedText; + private Expunge mExpungePolicy = Expunge.EXPUNGE_IMMEDIATELY; + private int mMaxPushFolders;",m prefix no longer in code style +1477,"@@ -168,6 +168,10 @@ func (kvb *kvStoreWithBuffer) MustDelete(ns string, key []byte) { + kvb.buffer.Delete(ns, key, ""failed to delete %x in %s"", key, ns) + } + ++func (kvb *kvStoreWithBuffer) Filter(ns string, c Condition) ([][]byte, [][]byte, error) { ++ return kvb.store.Filter(ns, c) ++} ++ + func (kvb *kvStoreWithBuffer) WriteBatch(b batch.KVStoreBatch) (err error) { + b.Lock() + defer func() {",need to filter the entities in buffer as well +1478,"@@ -12,6 +12,7 @@ import java.nio.charset.Charset; + import java.security.MessageDigest; + + public class FastBlurTransformation extends BitmapTransformation { ++ private static final String ID=""de.danoeh.antennapod.core.glide.FastBlurTransformation""; + + private static final String TAG = FastBlurTransformation.class.getSimpleName(); + ",Please add spaces before and after the equals sign +1479,"@@ -49,7 +49,7 @@ + #endif + #include ""common/sql.error_event.pb.h"" + #include ""common/sql.info_event.pb.h"" +-#include ""wrapper/amqpwrapper.h"" ++//#include ""wrapper/amqpwrapper.h"" + #include ""sq_sql_eventids.h"" + #include ""common/evl_sqlog_eventnum.h"" + ",This file could also be cleaned up/deleted. But lets do this separately after ensuring all the event logging has been ported to the current logmxevent_traf.cpp file completely. +1480,"@@ -7,12 +7,13 @@ module RSpec::Core::Formatters + it 'produces the expected full output' do + output = run_example_specs_with_formatter('failures') + expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) +- |./spec/rspec/core/resources/formatter_specs.rb:4:is marked as pending but passes +- |./spec/rspec/core/resources/formatter_specs.rb:36:fails +- |./spec/rspec/core/resources/formatter_specs.rb:40:fails twice +- |./spec/rspec/core/resources/formatter_specs.rb:47:fails with a backtrace that has no file +- |./spec/rspec/core/resources/formatter_specs.rb:53:fails with a backtrace containing an erb file +- |./spec/rspec/core/resources/formatter_specs.rb:71:raises ++ |./spec/rspec/core/resources/formatter_specs.rb:4:Expected example to fail since it is pending, but it passed. ++ |/home/roadster/dev/oss/rspec-core/spec/rspec/core/resources/formatter_specs.rb:37:expected: 2 got: 1 (compared using ==) ++ |/home/roadster/dev/oss/rspec-core/spec/rspec/core/resources/formatter_specs.rb:41:expected: 2 got: 1 (compared using ==) ++ |/home/roadster/dev/oss/rspec-core/spec/rspec/core/resources/formatter_specs.rb:42:expected: 4 got: 3 (compared using ==) ++ |/home/roadster/dev/oss/rspec-core/spec/rspec/core/resources/formatter_specs.rb:50:foo ++ |/foo.html.erb:1:Exception ++ |./spec/rspec/core/resources/formatter_specs.rb:71:boom + EOS + end + end",":thinking:, the line number here is the line of the example (`example.location`), that's probably why I finally chose to display the example title because it's what can be found on this line, and saying that the error is from there is confusing. But presenting the actual failures is indeed better, so maybe we can get the failure actual line number from the exception backtrace and then output two distinct lines for failures like this one?" +1481,"@@ -35,7 +35,7 @@ class WebDriver(ChromiumDriver): + def __init__(self, executable_path=""chromedriver"", port=DEFAULT_PORT, + options=None, service_args=None, + desired_capabilities=None, service_log_path=DEFAULT_SERVICE_LOG_PATH, +- chrome_options=None, service=None, keep_alive=True): ++ chrome_options=None, service=None, keep_alive=True, create_no_window=False): + """""" + Creates a new instance of the chrome driver. + Starts the service and then creates new instance of chrome driver.",We shouldn't add this as a new `kwarg` here. This should all be done on the options class +1482,"@@ -134,6 +134,7 @@ module Beaker + :openstack_keyname => ENV['OS_KEYNAME'], + :openstack_network => ENV['OS_NETWORK'], + :openstack_region => ENV['OS_REGION'], ++ :openstack_volume_support => ENV['OS_VOL_SUPPORT'] || true, + :jenkins_build_url => nil, + :validate => true, + :configure => true,",Should this be `OS_VOLUME_SUPPORT` to match the symbol key names? +1483,"@@ -38,6 +38,8 @@ + #include + #include ""heaptrace.h"" + ++static flux_msg_handler_t **handlers = NULL; ++ + static void start_cb (flux_t *h, flux_msg_handler_t *mh, + const flux_msg_t *msg, void *arg) + {","In C, file scope variables are already initialized to 0 so the ""= NULL"" is redundant. Not a big deal." +1484,"@@ -2,7 +2,7 @@ + + var nodeName = node.nodeName.toUpperCase(), + nodeType = node.type, +- doc = document; ++ doc = axe.commons.dom.getRootNode(node); + + if (node.getAttribute('aria-disabled') === 'true' || axe.commons.dom.findUp(node, '[aria-disabled=""true""]')) { + return false;","on line 40, the `relevantNode` can change and therefore the `doc` might change too for the lookup on line 43. I think this code should be moved to where the `doc` is actually being used" +1485,"@@ -57,6 +57,7 @@ namespace OpenTelemetry.Internal + { + throw new ArgumentOutOfRangeException( + nameof(milliseconds), ++ milliseconds, + string.Format(CultureInfo.InvariantCulture, ""milliseconds must be between {0} and {1}"", MinMilliseconds, MaxMilliseconds)); + } + ","nit: just to be similar to others, can you change to interpolation?" +1486,"@@ -111,6 +111,9 @@ type ControllerOptions struct { + // CertificateRequest -> Order. Slice of string literals that are + // treated as prefixes for annotation keys. + CopiedAnnotationPrefixes []string ++ ++ //Return full Certchain including root cert for k8s CSRs ++ FullCertChain bool + } + + const (","Would this make more sense as an option on an Issuer resource (specifically on the CA issuer) rather than as a flag? It's not ideal that we have a flag that _looks_ like it could be 'global' but is actually not IMO. Also, if Istio is reading the CSR object, is it possible for it to read the CA from the CSR itself too and append the two instead? Not sure if we ever decided whether to use annotations for this purpose @JoshVanL?" +1487,"@@ -10,6 +10,7 @@ class TargetType(Enum): + PANDAS = 'pandas' + FILE = 'file' + ++SERVER_TIME_F = ""%Y-%m-%dT%H:%M:%S"" + DATEF = '%F' + TIMEF = '%T' + DTIMEF = '%s %s' % (DATEF, TIMEF)","Because this acts as a coordination point between client and server, it should go in core.py instead of const.py (so eventually the server could use it to guarantee that it delivers dates in the expected format)." +1488,"@@ -212,8 +212,11 @@ func (r *createOrUpdate) Apply(obj *unstructured.Unstructured, subresources ...s + return + } + resource, err = r.options.Getter.Get(obj.GetName(), metav1.GetOptions{}) +- if err != nil && apierrors.IsNotFound(errors.Cause(err)) { +- return r.options.Creator.Create(obj, subresources...) ++ if err != nil { ++ if apierrors.IsNotFound(errors.Cause(err)) { ++ return r.options.Creator.Create(obj, subresources...) ++ } ++ return nil, err + } + return r.options.Updater.Update(resource, obj, subresources...) + }","expected statement, found 'else' (and 1 more errors)" +1489,"@@ -16,6 +16,17 @@ func FakeID(b byte, public bool) ID { + return ID{bytes} + } + ++// FakeIDRandomOrBust creates a fake public or private TLF ID from the given ++// byte, and fill the rest with empty bytes. ++func FakeIDRandomOrBust(b byte, public bool) ID { ++ id, err := MakeRandomID(public) ++ if err != nil { ++ panic(err) ++ } ++ id.id[0] = b ++ return id ++} ++ + // FakeIDByte returns the byte used to create a fake TLF ID with + // FakeID. + func FakeIDByte(id ID) byte {",IMO this doesn't need to be in the `kbfs` repo. And I don't like setting the byte. We can always compare with the randomly generated `TlfID`. +1490,"@@ -0,0 +1,7 @@ ++package constants ++ ++const ( ++ DeviceControllerModuleName = ""devicecontroller"" ++ CloudHubControllerModuleName = ""cloudhub"" ++ EdgeControllerModuleName = ""edgecontroller"" ++)",What's the difference from ModuleName in `pkg/apis/meta/v1alpha1/types.go`? +1491,"@@ -8,11 +8,12 @@ using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; +-using System.Reflection.Metadata; +-using System.Reflection.PortableExecutable; + using System.Text; + using Newtonsoft.Json.Linq; + using Newtonsoft.Json; ++using System.Security.Cryptography; ++using System.Reflection.PortableExecutable; ++using System.Reflection.Metadata; + + namespace Microsoft.DotNet.Build.Tasks + {",We shouldn't be changing this task as we are trying to break our dependency on it and switch to using the shipped version. +1492,"@@ -737,8 +737,10 @@ analyze_clean_call(dcontext_t *dcontext, clean_call_info_t *cci, instr_t *where, + * unless multiple regs are able to be skipped. + * XXX: This should probably be in arch-specific clean_call_opt.c. + */ ++ + if ((cci->num_simd_skip == 0 /* save all xmms */ && +- cci->num_regs_skip == 0 /* save all regs */ && ++ /* save all regs except 2, because XSP and XBP are commonly callee saved */ ++ cci->num_regs_skip <= 2 && + !cci->skip_save_flags) || + always_out_of_line) + cci->out_of_line_swap = true;","Shouldn't we have a low bar for generating out-of-line context switch, i.e., if we need save more than n (3?) simd or m (4) gprs we should go out-of-line? And it should be || instead &&. It seems the bar is still very high after this change." +1493,"@@ -23,6 +23,7 @@ import ( + ""go.opentelemetry.io/otel/api/kv"" + ""go.opentelemetry.io/otel/api/metric"" + ""go.opentelemetry.io/otel/api/metric/registry"" ++ ""go.opentelemetry.io/otel/sdk/instrumentation"" + ) + + // This file contains the forwarding implementation of metric.Provider",Should the API have a dependency on the SDK? +1494,"@@ -1475,7 +1475,7 @@ describe('Change Streams', function() { + } + }); + +- it('should resume piping of Change Streams when a resumable error is encountered', { ++ it.skip('should resume piping of Change Streams when a resumable error is encountered', { + metadata: { + requires: { + generators: true,",Is this a sometimes leaky test? +1495,"@@ -96,7 +96,11 @@ func (v ConstraintGenerator) typeof(n Node) (PolyType, error) { + ftv := n.ExternType.freeVars(nil) + subst := make(Substitution, len(ftv)) + for _, tv := range ftv { +- subst[tv] = v.cs.f.Fresh() ++ f := v.cs.f.Fresh() ++ for ftv.contains(f) { ++ f = v.cs.f.Fresh() ++ } ++ subst[tv] = f + } + t := subst.ApplyType(n.ExternType) + // Check if this type knows about its kind constraints","It should be possible to create a test case that enter the loop. That would be a good enough test case for me. Have a look at the extern type inference test cases that already exist. Since you can just pick the type variables the extern type use, you should be able to create a conflict that requires this loop to fix." +1496,"@@ -368,6 +368,11 @@ This initializes all modules such as audio, IAccessible, keyboard, mouse, and GU + wxLang=locale.FindLanguageInfo(lang.split('_')[0]) + if hasattr(sys,'frozen'): + locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),""locale"")) ++ # #8064: Wx might know the language, but may not actually contain a translation database for that language. ++ # If we try to initialize this language, wx will show a warning dialog. ++ # Therefore treat this situation like wx not knowing the language at all. ++ if not locale.IsAvailable(wxLang.Language): ++ wxLang=None + if wxLang: + try: + locale.Init(wxLang.Language)",It might make sense to log this. +1497,"@@ -340,12 +340,10 @@ module Blacklight + # too. These model names should not be `#dup`'ed or we might break ActiveModel::Naming. + def deep_copy + deep_dup.tap do |copy| +- copy.repository_class = self.repository_class +- copy.response_model = self.response_model +- copy.document_model = self.document_model +- copy.document_presenter_class = self.document_presenter_class +- copy.search_builder_class = self.search_builder_class +- copy.facet_paginator_class = self.facet_paginator_class ++ %w(repository_class response_model document_model document_presenter_class search_builder_class facet_paginator_class).each do |klass| ++ # Don't copy if nil, so as not to prematurely autoload default classes ++ copy.send(""#{klass}="", send(klass)) unless fetch(klass.to_sym, nil).nil? ++ end + end + end + alias_method :inheritable_copy, :deep_copy",Line is too long. [84/80] +1498,"@@ -22,6 +22,7 @@ from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + + + class Options(object): ++ KEY = ""goog:chromeOptions"" + + def __init__(self): + self._binary_location = ''",nice touch since Google likes to change things every now and then. +1499,"@@ -0,0 +1,19 @@ ++# Provides a helper utility for loading branding configs. ++module Branding ++ ++ module_function ++ ++ # Loads branding config from YAML file. ++ # ++ # @param keys [Array] A list of the keys to return configs for. ++ # ++ # @example Return a value ++ # Branding.fetch(:settings, :should_work) # => true ++ # Branding.fetch(:settings, :email) # => 'user@example.com' ++ # Branding.fetch(:settings, :missing) # => nil ++ # @return [Object] The value of the config ++ def fetch(*keys) ++ keys = keys.map(&:to_sym) ++ Rails.configuration.branding.dig(*keys) ++ end ++end",Thank you this is so much nicer than the old `Rails.configuration.branding['blah']['blah']['blah']` :) +1500,"@@ -29,6 +29,7 @@ class ResourceType(object): + FOLDER = 'folder' + PROJECT = 'project' + GROUP = 'group' ++ BACKEND_SERVICE = 'backend_service' + FORWARDING_RULE = 'forwarding_rule' + BUCKETS_ACL = 'buckets_acl' + CLOUDSQL_ACL = 'cloudsql_instances'",nit: Would you mind alpha-sorting this? +1501,"@@ -55,6 +55,8 @@ public class ManifestFiles { + * @return a {@link ManifestReader} + */ + public static ManifestReader read(ManifestFile manifest, FileIO io, Map specsById) { ++ Preconditions.checkArgument(manifest.content() == ManifestContent.DATA, ++ ""Cannot read a delete manifest with a ManifestReader: %s"", manifest); + InputFile file = io.newInputFile(manifest.path()); + InheritableMetadata inheritableMetadata = InheritableMetadataFactory.fromManifest(manifest); + return new ManifestReader(file, specsById, inheritableMetadata);","For my understanding, the DATA manifest & DELETE manifest could share the same read / write path so I think we could use the common reader+writer. Is there any other reason that we need to make them separate paths ?" +1502,"@@ -4,7 +4,7 @@ + plan_title = @plan.title + user_name = @plan.owner.name + helpdesk_email = Rails.configuration.branding[:organisation][:helpdesk_email] +- contact_us_url = Rails.configuration.branding[:organisation][:contact_us_url] ++ contact_us = Rails.configuration.branding[:organisation][:contact_us_url] || contact_us_url + email_subject = _('Query or feedback related to %{tool_name}') %{ :tool_name => tool_name } + %> + <% FastGettext.with_locale FastGettext.default_locale do %>",that change should be sufficient for avoiding the override of contact_us_url helper. The one defined at the .yml it is within a hash so no problem should arise. +1503,"@@ -56,7 +56,7 @@ return [ + 'choose_file' => 'Datei auswählen', + 'close' => 'Schließen', + 'create' => 'Erstellen', +- 'create_and_add_another' => 'Erstellen und weitere hinzufügen', ++ 'create_and_add_another' => 'Erstellen und weiteres Element hinzufügen', + 'create_and_continue' => 'Erstellen und weiter bearbeiten', + 'save' => 'Speichern', + 'save_and_continue' => 'Speichern und weiter bearbeiten',","We actually had a discussion about this exactly in #3470, some languages seem to go for one, some for the other " +1504,"@@ -50,6 +50,8 @@ public abstract class DynamicLangXApiView implements ViewModel { + + public abstract List longRunningDescriptors(); + ++ public abstract List grpcStreamingDescriptors(); ++ + public abstract List methodKeys(); + + public abstract String clientConfigPath();",Is PHP the first dynamic MVVM language with grpc streaming support? +1505,"@@ -41,6 +41,7 @@ SmilesMolSupplier::SmilesMolSupplier(const std::string &fileName, + if (!tmpStream || (!(*tmpStream)) || (tmpStream->bad())) { + std::ostringstream errout; + errout << ""Bad input file "" << fileName; ++ if (tmpStream) { delete tmpStream; } + throw BadFileException(errout.str()); + } + dp_inStream = static_cast(tmpStream);",the `if` isn't necessary here; it's safe to call `delete` on `nullptr` +1506,"@@ -156,6 +156,12 @@ ReturnCode_t DataWriter::assert_liveliness() + return impl_->assert_liveliness(); + } + ++bool DataWriter::remove_all_changes( ++ size_t* removed) ++{ ++ return impl_->remove_all_changes(removed); ++} ++ + } // namespace dds + } // namespace fastdds + } // namespace eprosima",Change if the method's name finally changes to `clear_history` as proposed elsewhere +1507,"@@ -34,9 +34,8 @@ def showHelp(helpId: str): + noHelpMessage = _(""No help available here."") + queueHandler.queueFunction(queueHandler.eventQueue, ui.message, noHelpMessage) + return +- +- import gui +- helpFile = gui.getDocFilePath(""userGuide.html"") ++ import documentationUtils ++ helpFile = documentationUtils.getDocFilePath(""userGuide.html"") + if helpFile is None: + # Translators: Message shown when trying to display context sensitive help, + # indicating that the user guide could not be found.",can this one also be moved to the top of the file? +1508,"@@ -26,6 +26,8 @@ type AppliedToGroup struct { + metav1.ObjectMeta + // Pods is a list of Pods selected by this group. + Pods []GroupMemberPod ++ // GroupMembers is a list of resources selected by this group. ++ GroupMembers []GroupMember + } + + // PodReference represents a Pod Reference.","So if I understand this correctly the externalEntities should be computed and stored in GroupMember, while current code usage of GroupMemberPod will be migrated to GroupMember later?" +1509,"@@ -1,13 +1,9 @@ +-using System; +-using System.Collections.Generic; +- +-namespace Datadog.Tracer ++namespace Datadog.Tracer + { + public static class Tags + { +- public const string Service = ""Datadog.Service""; +- public const string Resource = ""Datadog.Resource""; +- public const string Error = ""Datadog.Error""; +- public const string Type = ""Datadog.Type""; ++ public const string ServiceName = ""service.name""; ++ public const string ResourceName = ""resource.name""; ++ public const string SpanType = ""span.type""; + } + }",Don't we have tests to change after this breaking change? probably we're not using hard coded strings in our tests when we create a `Span`? +1510,"@@ -19,7 +19,7 @@ REPORT_FREQUENCY = 5000 + SUBSCRIBER_NAME = ""bq"" + KEYSPACE_NAME_INCOMING = ""ilisten"" + KEYSPACE_NAME_UNIQUE = ""ulisten"" +-APP_CREDENTIALS_FILE = ""bigquery-credentials.json"" ++APP_CREDENTIALS_FILE = os.environ['GOOGLE_APPLICATION_CREDENTIALS'] + + # TODO: + # Big query hardcoded data set ids",will this fail if the env variable doesn't exist? Is this the preferred behaviour? +1511,"@@ -325,8 +325,9 @@ class SpatialPooler(object): + + # Initialize a tiny random tie breaker. This is used to determine winning + # columns where the overlaps are identical. +- self._tieBreaker = 0.01*numpy.array([self._random.getReal64() for i in +- xrange(self._numColumns)]) ++ self._tieBreaker = numpy.array([0.01 * self._random.getReal64() for i in ++ xrange(self._numColumns)], ++ dtype=realDType) + + # 'self._connectedSynapses' is a similar matrix to 'self._permanences' + # (rows represent cortical columns, columns represent input bits) whose",bad line wrap +1512,"@@ -1245,6 +1245,14 @@ void rai::bootstrap_server::receive_header_action (boost::system::error_code con + }); + break; + } ++ case rai::message_type::bulk_pull_blocks: ++ { ++ auto this_l (shared_from_this ()); ++ boost::asio::async_read (*socket, boost::asio::buffer (receive_buffer.data () + 8, sizeof (rai::uint256_union) + sizeof (rai::uint256_union) + sizeof (bulk_pull_blocks_mode) + sizeof (uint32_t)), [this_l](boost::system::error_code const & ec, size_t size_a) { ++ this_l->receive_bulk_pull_blocks_action (ec, size_a); ++ }); ++ break; ++ } + case rai::message_type::frontier_req: + { + auto this_l (shared_from_this ());",What does the `8` here represent? Can you give it a name? +1513,"@@ -0,0 +1,12 @@ ++from pymatgen.ext.matproj import MPRester, TaskType ++import os ++material_ids = [""mp-32800"", ""mp-23494""] ++task_types = [TaskType.GGA_OPT, TaskType.GGA_UNIFORM] ++file_patterns = [""vasprun*"", ""OUTCAR*""] ++with MPRester(os.environ[""MP_API_KEY""]) as mpr: ++ meta, urls = mpr.get_download_info( ++ material_ids, task_types=task_types, file_patterns=file_patterns ++ ) ++ ++print(meta) ++print(urls)","`MPRester(os.environ[""MP_API_KEY""])` can be left simply as `MPRester()` and it will pick up the API key from the environment. What is the purpose of this file otherwise? Is it better suited for `dev_scripts`, or a test?" +1514,"@@ -11,7 +11,7 @@ + # + # It's strongly recommended to check this file into your version control system. + +-ActiveRecord::Schema.define(:version => 20121114193521) do ++ActiveRecord::Schema.define(:version => 20121212214215) do + + create_table ""announcements"", :force => true do |t| + t.datetime ""created_at"", :null => false",Looks like there may be more changes to this file than intended? +1515,"@@ -117,7 +117,7 @@ func (eb *eventbus) pubCloudMsgToEdge() { + body, ok := accessInfo.GetContent().(map[string]interface{}) + if !ok { + klog.Errorf(""Message is not map type"") +- return ++ continue + } + message := body[""message""].(map[string]interface{}) + topic := message[""topic""].(string)","when message type is not expected, contine to next loop instead of return to finish infinite loop" +1516,"@@ -2,6 +2,13 @@ package cmd + + import ( + ""fmt"" ++ ""os"" ++ osexec ""os/exec"" ++ ""path/filepath"" ++ ""strings"" ++ ""testing"" ++ ""time"" ++ + ""github.com/drud/ddev/pkg/ddevapp"" + ""github.com/drud/ddev/pkg/exec"" + ""github.com/drud/ddev/pkg/fileutil""",This change was not really intended but made by the linter of VS Code. And looking at other packages this looks like a best practise to place interal packages on the top and gh imports afterwards. +1517,"@@ -84,6 +84,10 @@ func (r *AWSMachine) ValidateUpdate(old runtime.Object) error { + delete(oldAWSMachineSpec, ""providerID"") + delete(newAWSMachineSpec, ""providerID"") + ++ // allow changes to instanceID ++ delete(oldAWSMachineSpec, ""instanceID"") ++ delete(newAWSMachineSpec, ""instanceID"") ++ + // allow changes to additionalTags + delete(oldAWSMachineSpec, ""additionalTags"") + delete(newAWSMachineSpec, ""additionalTags"")",instanceID should stay the same for a AWSMachine? +1518,"@@ -77,6 +77,7 @@ def _launch_local_catalog(): + env = dict(REGISTRY_URL=""http://localhost:5000"", + S3_PROXY_URL=open_config[""s3Proxy""], + ALWAYS_REQUIRE_AUTH=""false"", ++ NO_DOWNLOAD=""false"", + CATALOG_MODE=""LOCAL"", + SSO_AUTH=""DISABLED"", + PASSWORD_AUTH=""ENABLED"",",Since this is a dict don't you want `False` or do we clean that up elsewhere? +1519,"@@ -23,6 +23,7 @@ from luigi.scheduler import DISABLED, DONE, FAILED, CentralPlannerScheduler + + luigi.notifications.DEBUG = True + WORKER = 'myworker' ++HOST = 'localhost' + + + class CentralPlannerTest(unittest.TestCase):",what's the reason you had to add the `host` argument to all `get_work` calls? +1520,"@@ -37,6 +37,13 @@ public class UpdatePermissionRootCommand extends AbstractCommand { + } + } + ++ @Override ++ public boolean onSuccess(CommandContext ctxt, Object r) { ++ return ctxt.dataverses().index((Dataverse) r,true); ++ } ++ ++ ++ //TODO: Review this as this will never be an instance of Dataset, will it? + @Override + public Map> getRequiredPermissions() { + // for data file check permission on owning dataset",This will never be a dataset so we can simplify the code here +1521,"@@ -89,6 +89,15 @@ public abstract class AbstractBlockProcessor implements BlockProcessor { + + private final MiningBeneficiaryCalculator miningBeneficiaryCalculator; + ++ public AbstractBlockProcessor(final AbstractBlockProcessor blockProcessor) { ++ this( ++ blockProcessor.transactionProcessor, ++ blockProcessor.transactionReceiptFactory, ++ blockProcessor.blockReward, ++ blockProcessor.miningBeneficiaryCalculator, ++ blockProcessor.skipZeroBlockRewards); ++ } ++ + public AbstractBlockProcessor( + final TransactionProcessor transactionProcessor, + final MainnetBlockProcessor.TransactionReceiptFactory transactionReceiptFactory,",This should be moved into the PrivacyBlockProcessor instead of adding the constructor here. +1522,"@@ -38,7 +38,7 @@ import ( + ""github.com/pipe-cd/pipe/pkg/crypto"" + ""github.com/pipe-cd/pipe/pkg/datastore"" + ""github.com/pipe-cd/pipe/pkg/git"" +- ""github.com/pipe-cd/pipe/pkg/insight"" ++ insightfilestore ""github.com/pipe-cd/pipe/pkg/insight/insightstore"" + ""github.com/pipe-cd/pipe/pkg/model"" + ""github.com/pipe-cd/pipe/pkg/redis"" + ""github.com/pipe-cd/pipe/pkg/rpc/rpcauth""","nit: Remove ""insightfilestore"". I think ""insightstore"" is good enough and as I see we are using that name at other places too." +1523,"@@ -5,8 +5,8 @@ module RSpec::Core::Formatters + BisectProgressFormatter = Class.new(remove_const :BisectProgressFormatter) do + RSpec::Core::Formatters.register self + +- def bisect_round_finished(notification) +- return super unless notification.round == 3 ++ def bisect_round_started(notification) ++ return super unless @round_count == 3 + + Process.kill(""INT"", Process.pid) + # Process.kill is not a synchronous call, so to ensure the output",It looks like you've removed `bisect_round_finished` but kept `bisect_round_started`. Seems a little odd that they aren't paired. Not sure if there's anything to do about that though... +1524,"@@ -29,6 +29,8 @@ from qutebrowser.mainwindow.statusbar.percentage import Percentage + def percentage(qtbot): + """"""Fixture providing a Percentage widget."""""" + widget = Percentage() ++ # Force immedate update of percentage widget ++ widget.set_perc.throttle_set(-1) + qtbot.add_widget(widget) + return widget + ","I'm not sure how to fix the lint and mypy warnings on this line. I could just ignore them, but I feel like the linter should know this exists." +1525,"@@ -1,7 +1,7 @@ + 'use strict'; + + const Aspect = { +- SKIP_SESSION: Symbol('SKIP_SESSION') ++ SKIP_SESSION: 'SKIP_SESSION' + }; + + /**",why remove `Symbol`? +1526,"@@ -121,7 +121,7 @@ function getPunctuationRegExp() { + * Reference: https://en.wikipedia.org/wiki/Supplemental_Punctuation + * -> \u2E00-\u2E7F Reference + */ +- return /[\u2000-\u206F\u2E00-\u2E7F\\'!""#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]/g; ++ return /[\u2000-\u206F\u2E00-\u2E7F\\'!""#$%&£¢¥§€()*+,\-.\/:;<=>?@\[\]^_`{|}~±]/g; + } + + /**","Why are currency signs considered punctuation? They technically fall under the BMP range for Currency Symbols `\u20A0-\u20CF` (covered in `getUnicodeNonBmpRegExp`, which is itself a misnomer)" +1527,"@@ -71,6 +71,7 @@ setup( + # Metadata + author='Philippe BIONDI', + author_email='phil(at)secdev.org', ++ maintainer='Pierre LALET, Guillaume VALADON', + description='Scapy: interactive packet manipulation tool', + license='GPLv2', + url='http://www.secdev.org/projects/scapy',","You have forgotten a coma `,`" +1528,"@@ -35,7 +35,8 @@ def single_gpu_test(model, data_loader, show=False, out_dir=None): + img_show = mmcv.imresize(img_show, (ori_w, ori_h)) + + if out_dir: +- out_file = osp.join(out_dir, img_meta['filename']) ++ out_file = osp.join(out_dir, ++ osp.basename(img_meta['filename'])) + else: + out_file = None + ","For different datasets, we may want to save the images differently. Sometimes the datasets are categorized into several subfolders, and we want to keep it when saving visualization results, and sometimes we just want to save all images in `out_dir`. An argument may be added to control the behavior." +1529,"@@ -788,7 +788,12 @@ public class FlexBuffers { + if (io == other.length) { + // in our buffer we have an additional \0 byte + // but this does not exist in regular Java strings, so we return now +- return c1 - c2; ++ int cmp = c1 - c2; ++ if (cmp != 0 || bb.get(ia) == '\0') { ++ return cmp; ++ } else { ++ return 1; ++ } + } + } + while (c1 == c2);","if `other` could have a guaranteed `0` byte in it, this whole `if` could be removed, and above you could just add `|| c2 == '\0'` to get the same effect?" +1530,"@@ -33,7 +33,11 @@ import org.apache.iceberg.exceptions.AlreadyExistsException; + public class CachingCatalog implements Catalog { + + public static Catalog wrap(Catalog catalog) { +- return new CachingCatalog(catalog); ++ return wrap(catalog, true); ++ } ++ ++ public static Catalog wrap(Catalog catalog, Boolean caseSensitive) { ++ return new CachingCatalog(catalog, caseSensitive); + } + + private final Cache tableCache = Caffeine.newBuilder()",nit: can this be a primitive value? +1531,"@@ -333,9 +333,14 @@ func (b Browse) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { + + // Browsing navigation gets messed up if browsing a directory + // that doesn't end in ""/"" (which it should, anyway) +- if !strings.HasSuffix(r.URL.Path, ""/"") { +- staticfiles.RedirectToDir(w, r) +- return 0, nil ++ u := r.Context().Value(httpserver.OriginalURLCtxKey).(url.URL) ++ if u.Path == """" { ++ u.Path = ""/"" ++ } ++ if u.Path[len(u.Path)-1] != '/' { ++ u.Path += ""/"" ++ http.Redirect(w, r, u.String(), http.StatusMovedPermanently) ++ return http.StatusMovedPermanently, nil + } + + return b.ServeListing(w, r, requestedFilepath, bc)","This maybe not what we want. If `rewrite` occurred before, `r.URL.Path` contains the result and we should use it. Otherwise `rewrite` middleware will disfunction when combining with `browser`." +1532,"@@ -197,7 +197,7 @@ class Engine(object): + # :type exception: BaseException + exception = None + try: +- modules = [self.provisioning, self.aggregator] + self.reporters ++ modules = [self.aggregator, self.provisioning] + self.reporters + modules += self.services + for module in modules: + try:",Why change this? +1533,"@@ -5,9 +5,9 @@ declare(strict_types=1); + namespace Shopsys\FrameworkBundle\Component\Error; + + use Psr\Log\LoggerInterface; +-use Symfony\Component\HttpKernel\EventListener\ExceptionListener; ++use Symfony\Component\HttpKernel\EventListener\ErrorListener; + +-class NotLogFakeHttpExceptionsExceptionListener extends ExceptionListener ++class NotLogFakeHttpExceptionsExceptionListener extends ErrorListener + { + /** + * @var \Shopsys\FrameworkBundle\Component\Error\ErrorIdProvider|null", _nitpick_ Isn't it now actually NotLogFakeHttpExceptions**Error**Listener ? +1534,"@@ -82,6 +82,7 @@ namespace AutoRest.AzureResourceSchema + JsonSchema resourceDefinition = new JsonSchema(); + resourceDefinition.JsonType = ""object""; + ++ resourceDefinition.ResourceType = resourceType; + resourceDefinition.AddProperty(""type"", JsonSchema.CreateStringEnum(resourceType), true); + resourceDefinition.AddProperty(""apiVersion"", JsonSchema.CreateStringEnum(apiVersion), true); + ","Why not just look for the ""type"" property instead of creating a ResourceType property?" +1535,"@@ -360,7 +360,8 @@ func (bc *blockchain) context(ctx context.Context, tipInfoFlag bool) (context.Co + protocol.WithBlockchainCtx( + ctx, + protocol.BlockchainCtx{ +- Tip: tip, ++ Tip: tip, ++ ChainID: config.ChainID(), + }, + ), + bc.config.Genesis,",should use `bc.config.Blockchain.ChainID` +1536,"@@ -17,13 +17,12 @@ import java.util.Collections; + import java.util.List; + import org.springframework.boot.context.properties.ConfigurationProperties; + import zipkin.storage.elasticsearch.ElasticsearchStorage; +-import zipkin.storage.elasticsearch.NativeClient; + + @ConfigurationProperties(""zipkin.storage.elasticsearch"") + public class ZipkinElasticsearchStorageProperties { +- /** @see NativeClient.Builder#cluster(String) */ ++ /** @see ElasticsearchStorage.Builder#cluster(String) */ + private String cluster = ""elasticsearch""; +- /** @see NativeClient.Builder#hosts(List) */ ++ /** @see ElasticsearchStorage.Builder#hosts(List) */ + private List hosts = Collections.singletonList(""localhost:9300""); + /** @see ElasticsearchStorage.Builder#index(String) */ + private String index = ""zipkin"";",this doesn't need to know about NativeClient +1537,"@@ -233,7 +233,8 @@ class ViolationAccess(object): + violation.get('full_name', ''), + violation.get('resource_data', ''), + violation.get('violation_data', ''), +- violation.get('rule_name', '') ++ violation.get('rule_name', ''), ++ violation.get('resource_name', '') + ) + + violation = Violation(","I know we discussed if we should add in the resource_name to the hash, and I actually don't think it's required. The violation hash was recently updated (not released) to include the violated rule, so when the next release goes out, user's findings will get updated. The resource name doesn't hurt to have here, but not required." +1538,"@@ -14,8 +14,11 @@ static void surface_attach(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *buffer, int32_t sx, int32_t sy) { + struct wlr_surface *surface = wl_resource_get_user_data(resource); ++ int scale = surface->current.scale; + surface->pending.invalid |= WLR_SURFACE_INVALID_BUFFER; + surface->pending.buffer = buffer; ++ surface->texture->height_from_buffer = surface->texture->height / scale; ++ surface->texture->width_from_buffer = surface->texture->width / scale; + } + + static void surface_damage(struct wl_client *client,","The variable name is also misleading imo. The width from the buffer comes from `wl_shm_buffer_get_width` (or a similar EGL thing), which is what gets encoded into `surface->texture->width`." +1539,"@@ -179,6 +179,8 @@ class Listen(object): + 'time' : self.ts_since_epoch, + 'tags' : { + 'user_name' : escape(self.user_name), ++ 'artist_msid' : self.artist_msid, ++ 'recording_msid' : self.recording_msid, + }, + 'fields' : { + 'artist_name' : self.data['artist_name'],",Why are you using these tags to carry these msids? +1540,"@@ -439,8 +439,8 @@ int flb_config_set_property(struct flb_config *config, + flb_free(*s_val); /* release before overwriting */ + } + +- *s_val = malloc(flb_sds_len(tmp) * sizeof(char)); +- strncpy(*s_val, tmp, flb_sds_len(tmp)); ++ *s_val = malloc(flb_sds_len(tmp) * sizeof(char) + 1); ++ strcpy(*s_val, tmp); + flb_sds_destroy(tmp); + break; + default:",flb_strdup() should do the work here. note: use Fluent Bit memory wrappers +1541,"@@ -0,0 +1,6 @@ ++// Copyright 2020 The Swarm Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:generate sh -c ""protoc -I . -I \""$(go list -f '{{ .Dir }}' -m github.com/gogo/protobuf)/protobuf\"" --gogofaster_out=. retrieval.proto"" ++package pb",This line should be separated from the package declaration by one line as it is not the package description. +1542,"@@ -411,7 +411,7 @@ func TestRollDPoSConsensus(t *testing.T) { + require.NoError(t, err) + require.NoError(t, sf.Start(ctx)) + for j := 0; j < numNodes; j++ { +- ws, err := sf.NewWorkingSet(nil) ++ ws, err := sf.NewWorkingSet() + require.NoError(t, err) + _, err = accountutil.LoadOrCreateAccount(ws, chainRawAddrs[j], big.NewInt(0)) + require.NoError(t, err)","shadow: declaration of ""err"" shadows declaration at line 410 (from `govet`)" +1543,"@@ -1,15 +1,14 @@ + package task_config + + import ( ++ ""strings"" ++ ""time"" ++ ++ ds ""github.com/c2h5oh/datasize"" + ""github.com/sonm-io/core/insonmnia/structs"" + ""github.com/sonm-io/core/proto"" + ) + +-type DurationConfig struct { +- Since string `yaml:""since"" required:""true""` +- Until string `yaml:""until"" required:""true""` +-} +- + type RatingConfig struct { + Buyer int64 `yaml:""buyer"" required:""true""` + Supplier int64 `yaml:""supplier"" required:""true""`",Maybe next time better to make separate PR? +1544,"@@ -254,6 +254,14 @@ class MaskTestMixin(object): + ori_shapes = tuple(meta['ori_shape'] for meta in img_metas) + scale_factors = tuple(meta['scale_factor'] for meta in img_metas) + ++ if all(det_bbox.shape[0] == 0 for det_bbox in det_bboxes): ++ if torch.onnx.is_in_onnx_export(): ++ raise RuntimeError('[ONNX Error] Can not record MaskHead ' ++ 'as it has not been executed this time') ++ segm_results = [[[] for _ in range(self.mask_head.num_classes)] ++ for _ in range(len(det_bboxes))] ++ return segm_results ++ + # The length of proposals of different batches may be different. + # In order to form a batch, a padding operation is required. + if isinstance(det_bboxes, list):","line 316 also handles this case, need to simplify the logic." +1545,"@@ -122,9 +122,12 @@ type Options struct { + } + + // openBucket returns a GCS Bucket that communicates using the given HTTP client. +-func openBucket(ctx context.Context, bucketName string, client *gcp.HTTPClient, opts *Options) (driver.Bucket, error) { ++func openBucket(ctx context.Context, bucketName string, client *gcp.HTTPClient, opts *Options) (*bucket, error) { + if client == nil { +- return nil, errors.New(""OpenBucket requires an HTTP client"") ++ return nil, errors.New(""gcsblob.OpenBucket: client is required"") ++ } ++ if bucketName == """" { ++ return nil, errors.New(""gcsblob.OpenBucket: bucketName is required"") + } + c, err := storage.NewClient(ctx, option.WithHTTPClient(&client.Client)) + if err != nil {","We used to have a simple check for bucket and object names, we then decided to remove it and rely on the backend service to check for the name. Is there any reason to add an empty name check now?" +1546,"@@ -983,7 +983,11 @@ bool RTPSParticipantImpl::sendSync( + + for (auto& send_resource : send_resource_list_) + { +- send_resource->send(msg->buffer, msg->length, destination_loc); ++ // Calculate next timeout. ++ std::chrono::microseconds timeout = ++ std::chrono::duration_cast(max_blocking_time_point - std::chrono::steady_clock::now()); ++ ++ send_resource->send(msg->buffer, msg->length, destination_loc, timeout); + } + } + ",Line too long +1547,"@@ -638,6 +638,9 @@ MagicEffectNames magicEffectNames = { + {""orangeteleport"", CONST_ME_ORANGETELEPORT}, + {""greyteleport"", CONST_ME_GREYTELEPORT}, + {""lightblueteleport"", CONST_ME_LIGHTBLUETELEPORT}, ++ {""fatal"", CONST_ME_FATAL}, ++ {""dodge"", CONST_ME_DODGE}, ++ {""hourglass"", CONST_ME_HOURGLASS}, + }; + + ShootTypeNames shootTypeNames = {",This isn't aligned though. +1548,"@@ -533,7 +533,8 @@ class PAAHead(ATSSHead): + cls_scores. Besides, score voting is used when `` score_voting`` + is set to True. + """""" +- assert with_nms, 'PAA only supports ""with_nms=True"" now' ++ assert with_nms, 'PAA only supports ""with_nms=True"" now and it is ' \ ++ 'mean PAAHead does not support test-time augmentation' + assert len(cls_scores) == len(bbox_preds) == len(mlvl_anchors) + batch_size = cls_scores[0].shape[0] + ",it is mean -> it means PAAHead does not support test-time augmentation. +1549,"@@ -119,6 +119,7 @@ from invenio.legacy.bibcatalog.api import BIBCATALOG_SYSTEM + from invenio.legacy.bibdocfile.config import CFG_BIBDOCFILE_ICON_SUBFORMAT_RE, \ + CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT + from invenio.utils.hash import md5 ++from invenio.legacy.bibdocfile.registry import plugins + + import invenio.legacy.template + ",@lnielsen-cern thanks. I missed it :( +1550,"@@ -97,7 +97,7 @@ const AnalyticsAdSenseDashboardWidgetTopPagesTable = ( { data } ) => { + chartsEnabled: false, + links: rows.map( ( row ) => row.dimensions[ 1 ] || '/' ), + PrimaryLink: withSelect( ( select, { href = '/' } ) => { +- const serviceURL = select( STORE_NAME ).getServiceReportURL( 'content-pages', { ++ const serviceURL = select( STORE_NAME ).getServiceReportURL( 'content-drilldown', { + 'explorer-table.plotKeys': '[]', + '_r.drilldown': `analytics.pagePath:${ href }`, + } );","@tofumatt, has it been changed intentionally? It doesn't seem to be required in IB, plus we haven't had `content-drilldown` before... If it has been changed intentionally, then should we update the `AnalyticsDashboardWidget` component to be use `content-drilldown` instead of `content-pages` as well?" +1551,"@@ -16,6 +16,7 @@ + + from apiclient import discovery + from oauth2client.client import GoogleCredentials ++ + from retrying import retry + + from google.cloud.security.common.gcp_api._supported_apis import SUPPORTED_APIS",nit: don't think an extra line is needed here; as retrying is an installed library and should be grouped with the rest of the installed library. +1552,"@@ -123,6 +123,13 @@ type PrometheusSpec struct { + // The labels to add to any time series or alerts when communicating with + // external systems (federation, remote storage, Alertmanager). + ExternalLabels map[string]string `json:""externalLabels,omitempty""` ++ // Enable access to prometheus web admin API. Defaults to the value of `false`. ++ // WARNING: Enabling the admin APIs enables mutating endpoints, to delete data, ++ // shutdown Prometheus, and more. Enabling this should be done with care and the ++ // user is advised to add additional authentication authorization via a proxy to ++ // ensure only clients authorized to perform these actions can do so. ++ // For more information see https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis ++ EnableAdminAPI string `json:""enableAdminAPI,omitempty""` + // The external URL the Prometheus instances will be available under. This is + // necessary to generate correct URLs. This is necessary if Prometheus is not + // served from root of a DNS name.",This should be a bool +1553,"@@ -5129,12 +5129,12 @@ SwiftASTContext::GetReferentType(const CompilerType &compiler_type) { + + if (compiler_type.IsValid() && + llvm::dyn_cast_or_null(compiler_type.GetTypeSystem())) { +- swift::CanType swift_can_type(GetCanonicalSwiftType(compiler_type)); +- swift::TypeBase *swift_type = swift_can_type.getPointer(); +- if (swift_type && llvm::isa(swift_type)) ++ swift::Type swift_type(GetSwiftType(compiler_type)); ++ swift::TypeBase *swift_typebase = swift_type.getPointer(); ++ if (swift_type && llvm::isa(swift_typebase)) + return compiler_type; + +- auto ref_type = swift_can_type->getReferenceStorageReferent(); ++ auto ref_type = swift_type->getReferenceStorageReferent(); + return CompilerType(GetASTContext(), ref_type); + } + ",`if (llvm::dyn_cast_or_null(GetSwiftType(compiler_type).getPointer())` ? +1554,"@@ -144,13 +144,13 @@ func (e *deployExecutor) generateCanaryManifests(manifests []provider.Manifest, + + // Find config map manifests and duplicate them for CANARY variant. + configMaps := findConfigMapManifests(manifests) +- configMaps = duplicateManifests(configMaps, suffix) +- canaryManifests = append(canaryManifests, configMaps...) ++ canaryConfigMaps := duplicateManifests(configMaps, suffix) ++ canaryManifests = append(canaryManifests, canaryConfigMaps...) + + // Find secret manifests and duplicate them for CANARY variant. + secrets := findSecretManifests(manifests) +- secrets = duplicateManifests(secrets, suffix) +- canaryManifests = append(canaryManifests, secrets...) ++ canarySecrets := duplicateManifests(secrets, suffix) ++ canaryManifests = append(canaryManifests, canarySecrets...) + + // Generate new workload manifests for CANARY variant. + // The generated ones will mount to the new ConfigMaps and Secrets.","The `generateVariantWorkloadManifests` function below relies on the config manifests specified in Git, but it was passed with the newly created canary's manifests where their name was updated." +1555,"@@ -19,9 +19,10 @@ use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + class ErgonodeAccountExtension extends Extension implements PrependExtensionInterface + { + /** ++ * @throws \Exception ++ * + * @param array $configs + * +- * @throws \Exception + */ + public function load(array $configs, ContainerBuilder $container): void + {",are this docs neccesary ? +1556,"@@ -46,8 +46,8 @@ import java.util.List; + public class HttpCommandProcessor implements CommandProcessor { + + private String pathToServlet; +- private String browserStartCommand; +- private String browserURL; ++ private final String browserStartCommand; ++ private final String browserURL; + private String sessionId; + private String extensionJs; + private String rcServerLocation;",Can you please revert changes to files in the `thoughtworks` package? This is legacy code and we will eventually phase out RC. +1557,"@@ -13,6 +13,8 @@ void SoftmaxWithLossLayer::LayerSetUp( + LossLayer::LayerSetUp(bottom, top); + LayerParameter softmax_param(this->layer_param_); + softmax_param.set_type(""Softmax""); ++ // no loss weight for the Softmax internal layer. ++ softmax_param.clear_loss_weight(); + softmax_layer_ = LayerRegistry::CreateLayer(softmax_param); + softmax_bottom_vec_.clear(); + softmax_bottom_vec_.push_back(bottom[0]);","This change suppose to resolve issue #2968. `loss_weight` should be of length 2, the second entry is ignored." +1558,"@@ -242,7 +242,17 @@ var filesToIgnore = map[string]bool{ + + func ignoreFile(filename string) bool { + _, base := path.Split(filename) +- return filesToIgnore[base] || strings.HasPrefix(base, ""._"") ++ if filesToIgnore[base] || strings.HasPrefix(base, ""._"") { ++ return true ++ } ++ // Treat the files to ignore as prefixes, since if they ever ++ // conflict they'll have the conflict suffix. ++ for prefix := range filesToIgnore { ++ if strings.HasPrefix(base, prefix) { ++ return true ++ } ++ } ++ return false + } + + // processNotification adds the notification to the recomputer's",Is there an easy way to check for conflict suffix to avoid false positives here? +1559,"@@ -59,7 +59,7 @@ module Bolt + run_opts = {} + run_opts[:run_as] = opts['_run_as'] if opts['_run_as'] + begin +- task = apply_prep.get_task(opts['task'], params) ++ task = @context.get_validated_task(opts['task'], params) + rescue Bolt::Error => e + raise Bolt::Plugin::PluginError::ExecutionError.new(e.message, name, 'puppet_library') + end",`apply_prep.run_task` also seems like it can just use `@context.run_task` +1560,"@@ -36,6 +36,9 @@ define([""events"", ""layoutManager"", ""inputManager"", ""userSettings"", ""libraryMenu"" + showYear: true, + centerText: true + }); ++ ++ // FIXME: Wait for all sections to load ++ autoFocus(page); + }); + } + ",do you have any idea on how to fix it? +1561,"@@ -159,3 +159,19 @@ class GCSTargetTest(_GCSBaseTestCase, FileSystemTargetTestMixin): + + def create_target(self, format=None): + return gcs.GCSTarget(bucket_url(self.id()), format=format, client=self.client) ++ ++ def test_close_twice(self): ++ # Ensure gcs._DeleteOnCloseFile().close() can be called multiple times ++ tgt = self.create_target() ++ ++ with tgt.open('w') as dst: ++ dst.write('data') ++ assert dst.closed ++ dst.close() ++ assert dst.closed ++ ++ with tgt.open() as src: ++ assert src.read().strip() == 'data' ++ assert src.closed ++ src.close() ++ assert src.closed","You don't need to fix this (you've done so many iterations). But for next time, you can make this into a docstring so it'll have a nicer descriptive name when the tests are running." +1562,"@@ -90,6 +90,15 @@ func (eni *ENIAttachment) StopAckTimer() { + eni.ackTimer.Stop() + } + ++// HasExpired returns true if the ENI attachment object has exceeded the ++// threshold for notifying the backend of the attachment ++func (eni *ENIAttachment) HasExpired() bool { ++ eni.guard.RLock() ++ defer eni.guard.RUnlock() ++ ++ return time.Now().After(eni.ExpiresAt) ++} ++ + // String returns a string representation of the ENI Attachment + func (eni *ENIAttachment) String() string { + eni.guard.RLock()",When does 'expiresAt' change? Do you need this? +1563,"@@ -75,3 +75,15 @@ const Outfit* Outfits::getOutfitByLookType(PlayerSex_t sex, uint16_t lookType) c + } + return nullptr; + } ++ ++const Outfit* Outfits::getOutfitByLookType(uint16_t lookType) const ++{ ++ for (uint8_t sex = 0; sex <= 1; sex++) { ++ for (const Outfit& outfit : outfits[sex]) { ++ if (outfit.lookType == lookType) { ++ return &outfit; ++ } ++ } ++ } ++ return nullptr; ++}",There are enums for genders + `PLAYERSEX_LAST`. +1564,"@@ -23,9 +23,14 @@ func TestCalculateRollupFee(t *testing.T) { + data := make([]byte, 0, tt.dataLen) + fee := CalculateRollupFee(data, tt.gasUsed, big.NewInt(tt.dataPrice), big.NewInt(tt.executionPrice)) + +- dataFee := uint64((RollupBaseTxSize + len(data)) * int(tt.dataPrice)) ++ zeroes, ones := zeroesAndOnes(data) ++ zeroesCost := zeroes * 4 ++ onesCost := (96 + ones) * 16 ++ dataCost := zeroesCost + onesCost ++ dataFee := int64(dataCost) * tt.dataPrice ++ + executionFee := uint64(tt.executionPrice) * tt.gasUsed +- expectedFee := dataFee + executionFee ++ expectedFee := uint64(dataFee) + executionFee + if fee.Cmp(big.NewInt(int64(expectedFee))) != 0 { + t.Errorf(""rollup fee check failed: expected %d, got %s"", expectedFee, fee.String()) + }",Should this use the constants as well? Or intentionally covering the fact that the constants may change +1565,"@@ -58,7 +58,10 @@ class TopNContainer(object): + return self.extras + + def __len__(self): +- return self._size ++ if self._size >= 0: ++ return self._size ++ else: ++ return len(self.best) + + def __getitem__(self, which): + return self.best[which], self.extras[which]",The case of a negative size (= keep all elements) was not handled in this function. +1566,"@@ -70,13 +70,13 @@ var keys = map[Key]string{ + EnableNamespaceNotActiveAutoForwarding: ""system.enableNamespaceNotActiveAutoForwarding"", + TransactionSizeLimit: ""system.transactionSizeLimit"", + MinRetentionDays: ""system.minRetentionDays"", +- MaxWorkflowTaskTimeout: ""system.maxWorkflowTaskTimeout"", + DisallowQuery: ""system.disallowQuery"", + EnableBatcher: ""worker.enableBatcher"", + EnableParentClosePolicyWorker: ""system.enableParentClosePolicyWorker"", + EnableStickyQuery: ""system.enableStickyQuery"", + EnablePriorityTaskProcessor: ""system.enablePriorityTaskProcessor"", + EnableAuthorization: ""system.enableAuthorization"", ++ EnableInfiniteTimeout: ""system.enableInfiniteTimeout"", + + // size limit + BlobSizeLimitError: ""limit.blobSize.error"",",I think we should keep this dynamic config knob for operations purpose. +1567,"@@ -60,7 +60,6 @@ class TestCharacterOffsets(unittest.TestCase): + obj = BasicTextProvider(text=u""\U0001f926\U0001f60a\U0001f44d"") # 🤦😊👍 + ti = obj.makeTextInfo(Offsets(5, 5)) + ti.expand(textInfos.UNIT_CHARACTER) # Range at 👍 +- self.assertEqual(ti.offsets, (4, 6)) # Two offsets + ti.move(textInfos.UNIT_CHARACTER, -1) + ti.expand(textInfos.UNIT_CHARACTER) # Range at 😊 + self.assertEqual(ti.offsets, (2, 4)) # Two offsets",Was this intentional? Perhaps this could be replaced with another way to check the offsets? +1568,"@@ -86,6 +86,7 @@ type PipelineManifest struct { + Version PipelineSchemaMajorVersion `yaml:""version""` + Source *Source `yaml:""source""` + Stages []PipelineStage `yaml:""stages""` ++ // ArtifactBuckets? + } + + // Source defines the source of the artifacts to be built and deployed.","the buckets are created via the stackset, customers don't need to provide them" +1569,"@@ -25,7 +25,7 @@ module Blacklight + # Execute a search query against solr + # @param [Hash] solr query parameters + def search params = {} +- send_and_receive blacklight_config.solr_path, { qt: blacklight_config.qt }.merge(params) ++ send_and_receive blacklight_config.solr_path, params.merge({ qt: blacklight_config.qt }) + end + + ##",This doesn't have the same behavior as before. Maybe you want `reverse_merge` (and it either just works or we implement it on `Blacklight::Solr::Request`) +1570,"@@ -6,6 +6,7 @@ module Travis + + def setup + super ++ cmd ""export PATH=/usr/local/ghc/#{ghc_version}/bin/:$PATH"" + cmd 'cabal update', fold: 'cabal', retry: true + end + ","This should be ` /$(ghc_find #{config[:ghc]})/ ` instead of ` /#{ghc_version}/ `, I think." +1571,"@@ -374,7 +374,7 @@ define([""appSettings"", ""browser"", ""events"", ""htmlMediaHelper""], function (appSet + return -1 !== supportedFeatures.indexOf(command.toLowerCase()); + }, + preferVisualCards: browser.android || browser.chrome, +- moreIcon: browser.android ? ""dots-vert"" : ""dots-horiz"", ++ moreIcon: browser.android ? ""more_vert"" : ""more_horiz"", + getSyncProfile: getSyncProfile, + getDefaultLayout: function () { + if (window.NativeShell) {",We should deprecate this at some point. +1572,"@@ -49,7 +49,9 @@ class FCOSHead(nn.Module): + use_sigmoid=True, + loss_weight=1.0), + conv_cfg=None, +- norm_cfg=dict(type='GN', num_groups=32, requires_grad=True)): ++ norm_cfg=dict(type='GN', num_groups=32, requires_grad=True), ++ center_sampling=False, ++ center_sample_radius=1.5): + super(FCOSHead, self).__init__() + + self.num_classes = num_classes",Move these two arguments before `loss_cls`. +1573,"@@ -93,10 +93,16 @@ func GenerateSelfSignedX509CA(commonName string, extUsage []x509.ExtKeyUsage, ke + } + + // GenerateServerX509UsingCA generates a TLS serverCert that is self-signed +-func GenerateServerX509UsingCA(commonName string, ca *tls.Certificate) (*tls.Certificate, *rsa.PrivateKey, error) { ++func GenerateServerX509UsingCAAndSerialNumber(commonName string, serialNumber int64, ca *tls.Certificate) (*tls.Certificate, *rsa.PrivateKey, error) { + now := time.Now().UTC() + +- i := mathrand.Int63n(100000000000000000) ++ var i int64 ++ if serialNumber == 0 { ++ i = mathrand.Int63n(100000000000000000) ++ } else { ++ i = serialNumber ++ } ++ + template := &x509.Certificate{ + SerialNumber: big.NewInt(i), + Subject: pkix.Name{",[Super NIT]: i := serialNumber if i == 0 { i = mathrand.Int63n(...) } +1574,"@@ -14,8 +14,8 @@ namespace Microsoft.CodeAnalysis.Sarif.ConvertToSarif + public string InputFilePath { get; internal set; } + + [Option( +- 'f', +- ""format"", ++ 't', ++ ""tool"", + HelpText = ""The tool format of the input file."")] + public ToolFormat ToolFormat { get; internal set; } + ",-f short form here collided with --force. :) +1575,"@@ -12,6 +12,5 @@ describe('preact', () => { + expect(cloneElement).to.be.a('function'); + expect(createContext).to.be.a('function'); + expect(options).to.exist.and.be.an('object'); +- // expect(rerender).to.be.a('function'); + }); + });",I think it is better to describe in the release note that `rerender()` was removed. +1576,"@@ -3,5 +3,5 @@ VERSION = ""."".join(str(i) for i in IVERSION) + PATHOD = ""pathod "" + VERSION + MITMPROXY = ""mitmproxy "" + VERSION + +-if __name__ == ""__main__"": ++if __name__ == ""__main__"": # pragma: no cover + print(VERSION)","We could also test this easily with `runpy.run_module`, what do you think?" +1577,"@@ -388,8 +388,10 @@ func decode(v reflect.Value, d Decoder) error { + if err != nil { + return err + } +- v.Set(reflect.ValueOf(val)) +- return nil ++ if v.Type().AssignableTo(reflect.TypeOf(val)) { ++ v.Set(reflect.ValueOf(val)) ++ return nil ++ } + } + + // Handle implemented interfaces first.","Is it OK to fall through if it's not assignable? I was kind of surprised when the tests passed. Maybe one of the options below ends up working? For the new tests, this panics because `**not assignable uuid.UUID to []uint8**`. `uuid.UUID` is an array, not a slice." +1578,"@@ -133,7 +133,8 @@ func runAPIAndWait(ctx context.Context, nd *node.Node, config *config.Config, re + ctx: context.Background(), + api: api, + porcelainAPI: nd.PorcelainAPI, +- blockpAPI: nd.BlockAPI, ++ blockAPI: nd.BlockAPI, ++ retrievalAPI: nd.RetrievalAPI, + } + + cfg := cmdhttp.NewServerConfig()",I know this is after the fact but imo blockAPI should be blockMiningAPI. +1579,"@@ -13,7 +13,11 @@ use Ergonode\SharedKernel\Domain\AbstractCode; + + class AttributeCode extends AbstractCode + { +- public const PATTERN = '/^([a-zA-Z0-9_]+)$/'; ++ public const NOT_SYSTEM_ATTRIBUTE_PATTERN = '/^(?!'.self::SYSTEM_ATTRIBUTE_PREFIX.')[a-zA-Z0-9_]+$/'; ++ ++ public const SYSTEM_ATTRIBUTE_PATTERN = '/^'.self::SYSTEM_ATTRIBUTE_PREFIX.'[a-zA-Z0-9_]+$/'; ++ ++ public const SYSTEM_ATTRIBUTE_PREFIX = 'esa_'; + + public function __construct(string $value) + {",it's just a pattern as it was. SystemAttributeCode should have it's own definition and validate by it +1580,"@@ -0,0 +1,17 @@ ++/* Copyright (c) 2019 vesoft inc. All rights reserved. ++ * ++ * This source code is licensed under Apache 2.0 License, ++ * attached with Common Clause Condition 1.0, found in the LICENSES directory. ++ */ ++ ++#include ""LookUpEdgeIndexProcessor.h"" ++ ++namespace nebula { ++namespace storage { ++ ++void LookUpEdgeIndexProcessor::process(const cpp2::LookUpIndexRequest& req) { ++ UNUSED(req); ++} ++} // namespace storage ++} // namespace nebula ++","Similar to the code block when we use prefix, maybe we can unify them to base?" +1581,"@@ -100,6 +100,15 @@ func (in *PodChaos) ValidateScheduler(spec *field.Path) field.ErrorList { + allErrs = append(allErrs, err...) + } + break ++ case PodNotReadyAction: ++ // We choose to ignore the Duration property even user define it ++ if in.Spec.Scheduler == nil { ++ allErrs = append(allErrs, field.Invalid(schedulerField, in.Spec.Scheduler, ValidatePodchaosSchedulerError)) ++ } else { ++ _, err := ParseCron(in.Spec.Scheduler.Cron, schedulerField.Child(""cron"")) ++ allErrs = append(allErrs, err...) ++ } ++ break + default: + err := fmt.Errorf(""podchaos[%s/%s] have unknown action type"", in.Namespace, in.Name) + log.Error(err, ""Wrong PodChaos Action type"")",I think `Duration` is useful for this action and we shouldn't ignore it. +1582,"@@ -243,13 +243,10 @@ func (s *stream) Write(p []byte) (int, error) { + s.mutex.Lock() + } + +- if err != nil { +- return 0, err +- } + if s.err != nil { +- return len(p) - len(s.dataForWriting), s.err ++ err = s.err + } +- return len(p), nil ++ return len(p) - len(s.dataForWriting), err + } + + func (s *stream) GetWriteOffset() protocol.ByteCount {","Everything below here can be replaced with `return s.err, len(p) - len(s.dataForWriting)`." +1583,"@@ -84,6 +84,12 @@ namespace Impl { + HIPLockArrays g_host_hip_lock_arrays = {nullptr, nullptr, 0}; + + void initialize_host_hip_lock_arrays() { ++#ifdef KOKKOS_ENABLE_IMPL_DESUL_ATOMICS ++ desul::Impl::init_lock_arrays(); ++ ++ DESUL_ENSURE_HIP_LOCK_ARRAYS_ON_DEVICE(); ++#endif ++ + if (g_host_hip_lock_arrays.atomic != nullptr) return; + HIP_SAFE_CALL(hipMalloc( + &g_host_hip_lock_arrays.atomic,","Again, we can also guard `g_host_hip_lock_arrays.atomic`, can't we?" +1584,"@@ -69,12 +69,13 @@ class ImportSimpleProductCommandHandler + ); + + if (!empty($attributesToRedispatch)) { +- $this->commandBus->dispatch(new ImportProductAttributesValueCommand( ++ $ImportProductAttributesValueCommand = new ImportProductAttributesValueCommand( + $command->getId(), + $command->getImportId(), + $attributesToRedispatch, + $command->getSku() +- )); ++ ); ++ $this->commandBus->dispatch($ImportProductAttributesValueCommand, true); + } + $this->repository->markLineAsSuccess($command->getId(), $product->getId()); + } catch (ImportException $exception) {",Variable name should start from lowercase latter +1585,"@@ -47,12 +47,12 @@ import ( + // certificate, ca, and private key is stored into the target Secret to + // complete Issuing the Certificate. + func TestIssuingController(t *testing.T) { +- config, stopFn := framework.RunControlPlane(t) +- defer stopFn() +- +- ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) ++ ctx, cancel := context.WithTimeout(context.Background(), time.Second*40) + defer cancel() + ++ config, stopFn := framework.RunControlPlane(t, ctx) ++ defer stopFn() ++ + // Build, instantiate and run the issuing controller. + kubeClient, factory, cmCl, cmFactory := framework.NewClients(t, config) + controllerOptions := controllerpkg.CertificateOptions{",Why has this timeout doubled? +1586,"@@ -113,7 +113,7 @@ type Config struct { + IptablesRefreshInterval time.Duration `config:""seconds;90""` + IptablesPostWriteCheckIntervalSecs time.Duration `config:""seconds;30""` + IptablesLockFilePath string `config:""file;/run/xtables.lock""` +- IptablesLockTimeoutSecs time.Duration `config:""seconds;30""` ++ IptablesLockTimeoutSecs time.Duration `config:""seconds;0""` + IptablesLockProbeIntervalMillis time.Duration `config:""millis;50""` + IpsetsRefreshInterval time.Duration `config:""seconds;10""` + MaxIpsetSize int `config:""int;1048576;non-zero""`","Should IptablesPostWriteCheckIntervalSecs be set back to its previous smaller value, if use of the iptables lock is disabled?" +1587,"@@ -335,6 +335,13 @@ class WebEngineCaret(browsertab.AbstractCaret): + """""" + if js_elem is None: + return ++ if js_elem == ""focused"": ++ # we had a focused element, not a selected one. Just send ++ if tab: ++ self._tab.key_press(Qt.Key_Enter, modifier=Qt.ControlModifier) ++ else: ++ self._tab.key_press(Qt.Key_Enter) ++ + assert isinstance(js_elem, dict), js_elem + elem = webengineelem.WebEngineElement(js_elem, tab=self._tab) + if tab:","You're missing a `return` here, but I'll add it :smile:" +1588,"@@ -116,7 +116,7 @@ static bool gles2_render_texture_with_matrix(struct wlr_renderer *wlr_renderer, + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); + struct wlr_gles2_texture *texture = +- get_gles2_texture_in_context(wlr_texture); ++ gles2_get_texture(wlr_texture); + + struct wlr_gles2_tex_shader *shader = NULL; + GLenum target = 0;",Can you try adding back this assertion? I'd like to assert that the texture has been created in the same context as the renderer. +1589,"@@ -234,7 +234,8 @@ class RouteFactory(object): + required_permission = self.method_permissions.get(method) + + # For create permission, the object id is the plural endpoint. +- collection_path = service.collection_path.format(**request.matchdict) ++ plural_endpoint = service.collection_path.decode('utf-8') ++ collection_path = plural_endpoint.format(**request.matchdict) + + # In the case of a ""PUT"", check if the targetted record already + # exists, return ""write"" if it does, ""create"" otherwise.",This won't work with Python 3 because it will already be a string. In that case we need to use `decode_header` from utils. +1590,"@@ -28,6 +28,8 @@ module Mongoid + raise Errors::InvalidDiscriminatorKeyTarget.new(self, self.superclass) + end + ++ self._clear_types if self.respond_to?(:_clear_types) ++ + if value + Mongoid::Fields::Validators::Macro.validate_field_name(self, value) + value = value.to_s",Why is the respond_to check here? +1591,"@@ -229,7 +229,7 @@ class FunctionDocblockManipulator + continue; + } + +- if ($chars[$i] === '\\' || preg_match('/\w/', $char)) { ++ if ($char === '\\' || preg_match('/\w/', $char)) { + if ($this->return_typehint_start === null) { + $this->return_typehint_start = $i + $end_bracket_position + 1; + }","@orklah are you sure it's the same as `$chars[$i]`? It looks like `$i` is changed above, after `$char` assignment." +1592,"@@ -22,7 +22,7 @@ TEST(DeleteVertexTest, SimpleTest) { + std::unique_ptr kv(TestUtils::initKV(rootPath.path())); + // Add vertices + { +- auto* processor = AddVerticesProcessor::instance(kv.get(), nullptr, nullptr); ++ auto* processor = AddVerticesProcessor::instance(kv.get(), nullptr, nullptr, nullptr); + cpp2::AddVerticesRequest req; + req.space_id = 0; + req.overwritable = false;",I have a question? How do I construct a indexManager for testcase? +1593,"@@ -73,6 +73,9 @@ int __FPGA_API__ opae_plugin_configure(opae_api_adapter_table *adapter, + { + UNUSED_PARAM(jsonConfig); + ++ if (adapter == NULL || adapter->plugin.dl_handle == NULL) ++ return -1; ++ + adapter->fpgaOpen = dlsym(adapter->plugin.dl_handle, ""xfpga_fpgaOpen""); + adapter->fpgaClose = + dlsym(adapter->plugin.dl_handle, ""xfpga_fpgaClose"");",These checks aren't needed. See pluginmgr.c : opae_plugin_mgr_load_dflt_plugins( ). +1594,"@@ -554,15 +554,14 @@ class SearchRequest + + /** + * Method to check if the query string is an empty string +- * (also empty string or whitespaces only are handled as empty). ++ * (also whitespaces only are handled as empty). + * + * When no query string is set (null) the method returns false. + * @return bool + */ + public function getRawUserQueryIsEmptyString() + { +- $path = $this->prefixWithNamespace('q'); +- $query = $this->argumentsAccessor->get($path, null); ++ $query = $this->getRawUserQuery(); + + if ($query === null) { + return false;",Please take a care about prefixing. +1595,"@@ -70,6 +70,17 @@ public interface WorldUpdater extends MutableWorldView { + return account == null ? createAccount(address) : account; + } + ++ /** ++ * Retrieves the provided account for a sender of a transaction if it exists, or creates it if it ++ * doesn't. ++ * ++ * @param address the address of the account. ++ * @return the account {@code address}, or {@code null} if the account does not exist. ++ */ ++ default EvmAccount getOrCreateSenderAccount(final Address address) { ++ return getOrCreate(address); ++ } ++ + /** + * Retrieves the provided account, returning a modifiable object (whose updates are accumulated by + * this updater).",this line doesn't match what the rest says +1596,"@@ -1,4 +1,4 @@ +-// +build !linux linux,android ++// +build windows linux,android + + /* + * Copyright (C) 2017 The ""MysteriumNetwork/node"" Authors.","Since it's not working for linux, maybe leave the !linux in there as well?" +1597,"@@ -60,6 +60,9 @@ func (i *IncludeWorkflow) populate(ctx context.Context, s *Step) error { + + // Copy Sources up to parent resolving relative paths as we go. + for k, v := range i.w.Sources { ++ if v == """" { ++ continue ++ } + if _, ok := s.w.Sources[k]; ok { + return fmt.Errorf(""source %q already exists in workflow"", k) + }","Should we remove the key-value pair entirely? Same for workflows in general. We have a ""sourceExists"" method that checks if a key is there if I remember correctly." +1598,"@@ -96,7 +96,7 @@ public class ContentSoqlSyncDownTarget extends SoqlSyncDownTarget { + + @Override + public JSONArray startFetch(SyncManager syncManager, long maxTimeStamp) throws IOException, JSONException { +- String queryToRun = maxTimeStamp > 0 ? SoqlSyncDownTarget.addFilterForReSync(getQuery(), maxTimeStamp) : getQuery(); ++ String queryToRun = maxTimeStamp > 0 ? SoqlSyncDownTarget.addFilterForReSync(getQuery(), getModificationDateFieldName(), maxTimeStamp) : getQuery(); + syncManager.getRestClient().sendSync(RestRequest.getRequestForResources(syncManager.apiVersion)); // cheap call to refresh session + RestRequest request = buildQueryRequest(syncManager.getRestClient().getAuthToken(), queryToRun); + RestResponse response = syncManager.sendSyncWithSmartSyncUserAgent(request);",Unrelated bug fix +1599,"@@ -173,15 +173,15 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir + }; + + if (status === 'completed') { +- notification.title = globalize.translate('PackageInstallCompleted').replace('{0}', installation.Name + ' ' + installation.Version); ++ notification.title = globalize.translate('PackageInstallCompleted', installation.Name + ' ' + installation.Version); + notification.vibrate = true; + } else if (status === 'cancelled') { +- notification.title = globalize.translate('PackageInstallCancelled').replace('{0}', installation.Name + ' ' + installation.Version); ++ notification.title = globalize.translate('PackageInstallCancelled', installation.Name + ' ' + installation.Version); + } else if (status === 'failed') { +- notification.title = globalize.translate('PackageInstallFailed').replace('{0}', installation.Name + ' ' + installation.Version); ++ notification.title = globalize.translate('PackageInstallFailed', installation.Name + ' ' + installation.Version); + notification.vibrate = true; + } else if (status === 'progress') { +- notification.title = globalize.translate('InstallingPackage').replace('{0}', installation.Name + ' ' + installation.Version); ++ notification.title = globalize.translate('InstallingPackage', installation.Name + ' ' + installation.Version); + + notification.actions = + [",We probably want to let the translation library handle the string replacement for these as well. +1600,"@@ -272,8 +272,7 @@ func newAdminMembershipCommands() []cli.Command { + { + Name: ""list_db"", + Usage: ""List cluster membership items"", +- Flags: append( +- getDBFlags(), ++ Flags: []cli.Flag{ + cli.StringFlag{ + Name: FlagHeartbeatedWithin, + Value: ""15m"",","should combine these 2 list (list_gossip and list_db) into just one list command, and show the discrepancy between the 2 if any." +1601,"@@ -21,6 +21,11 @@ class ProposalPolicy + !@proposal.approved? + end + ++ def approve_reject? ++ actionable_approvers = @proposal.currently_awaiting_approvers ++ actionable_approvers.include? @user ++ end ++ + def edit? + self.test_all(:edit?) + end",What do you think about prefixing the Policy method names with `can_`? +1602,"@@ -29,11 +29,10 @@ + #include + #include + +-/* HTTP Credentials Endpoints have a standard set of JSON Keys */ +-#define AWS_HTTP_RESPONSE_ACCESS_KEY ""AccessKeyId"" +-#define AWS_HTTP_RESPONSE_SECRET_KEY ""SecretAccessKey"" +-#define AWS_HTTP_RESPONSE_TOKEN ""Token"" +-#define AWS_HTTP_RESPONSE_EXPIRATION ""Expiration"" ++#define AWS_CREDENTIAL_RESPONSE_ACCESS_KEY ""AccessKeyId"" ++#define AWS_CREDENTIAL_RESPONSE_SECRET_KEY ""SecretAccessKey"" ++#define AWS_HTTP_RESPONSE_TOKEN ""Token"" ++#define AWS_CREDENTIAL_RESPONSE_EXPIRATION ""Expiration"" + + #define ECS_CREDENTIALS_HOST ""169.254.170.2"" + #define ECS_CREDENTIALS_HOST_LEN 13","Based on the docs, credential process can return a key `SessionToken`" +1603,"@@ -9,8 +9,12 @@ export default Ember.Mixin.create({ + + if (birthDate) { + if (birthDate.getFullYear === undefined) { +- birthDate = moment(birthDate, 'l').toDate(); ++ birthDate = moment(birthDate, 'LLL').toDate(); + } ++ ++ birthDate.setHours(0, 0, 0, 0); ++ today.setHours(0, 0, 0, 0); ++ + if (birthDate.getFullYear !== undefined) { + years = today.getFullYear() - birthDate.getFullYear(); + if (today.getMonth() < birthDate.getMonth()",I think this if should be removed (see issue) +1604,"@@ -19,6 +19,7 @@ import ( + + log ""github.com/sirupsen/logrus"" + ++ ""github.com/projectcalico/felix/ipsets"" + ""github.com/projectcalico/libcalico-go/lib/set"" + ) + ",I would avoid importing `felix/ipsets` package because this package is the windows equivalent and should be at the same level of `felix/ipsets`. We could add linux specific dependencies into `felix/ipsets` later and it will break Windows build. +1605,"@@ -19,6 +19,7 @@ + # along with qutebrowser. If not, see . + + """"""Generate the html documentation based on the asciidoc files."""""" ++from typing import List, Tuple + + import re + import os","nitpick: Please move this down to the other imports, as it's a Python stdlib import." +1606,"@@ -13,7 +13,8 @@ + // limitations under the License. + + // Package blob provides an easy and portable way to interact with blobs +-// within a storage location, hereafter called a ""bucket"". ++// within a storage location, hereafter called a ""bucket"". See ++// https://gocloud.dev/howto/blob/ for getting started guides. + // + // It supports operations like reading and writing blobs (using standard + // interfaces from the io package), deleting blobs, and listing blobs in a","""for getting started guides"" reads a bit weird, like it's missing punctuation. Maybe just ""for a tutorial""?" +1607,"@@ -50,9 +50,9 @@ class Formats extends AbstractBase + * Constructor + * + * @param bool $enabled is this tab enabled? +- * @param bool $urc use recaptcha? ++ * @param bool $uc use captcha? + */ +- public function __construct($enabled = true, $urc = false) ++ public function __construct($enabled = true, $uc = false) + { + $this->enabled = $enabled; + }","This looks like a dead parameter -- maybe a copy and paste error. If it's truly unused, maybe you can open a separate PR to simply delete it, and then it's one less detail to worry about here." +1608,"@@ -42,7 +42,11 @@ func (m *VerticaRowReader) GetNextRow() ([]values.Value, error) { + row := make([]values.Value, len(m.columns)) + for i, col := range m.columns { + switch col := col.(type) { +- case bool, int, uint, int64, uint64, float64, string: ++ case int: ++ row[i] = values.NewInt(int64(col)) ++ case uint: ++ row[i] = values.NewUInt(uint64(col)) ++ case bool, int64, uint64, float64, string: + row[i] = values.New(col) + case time.Time: + row[i] = values.NewTime(values.ConvertTime(col))","Nit: Should we add support for `int` and `uint` in the `values.New()` function? That would allow us to to handle all of these types in one case. Maybe there's a good reason why we don't do that already, but I'm not sure what it is." +1609,"@@ -14,7 +14,7 @@ import net.sourceforge.pmd.RuleViolation; + /** + * A {@link RuleViolation} implementation that is immutable, and therefore cache friendly + */ +-public final class CachedRuleViolation implements RuleViolation { ++public class CachedRuleViolation implements RuleViolation { + + private final CachedRuleMapper mapper; + ","if you are not dealing with cache now, please revert these changes. On their own they make little sense" +1610,"@@ -56,7 +56,7 @@ public abstract class NodeGenerator extends Generator { + throw new AssertionError(f(""Wanted to regenerate a method with signature %s in %s, but it wasn't there."", callable.getSignature(), containingClassOrInterface.getNameAsString())); + }); + } +- ++ + private void addMethod( + ClassOrInterfaceDeclaration containingClassOrInterface, + CallableDeclaration callable,",Wearing my extra-douche-bag hat I would say not spaces on a blank line. Maybe at some point we could have some automated process remove these things. For now I would not bother changing it. +1611,"@@ -0,0 +1,7 @@ ++package de.danoeh.antennapod.core.event; ++ ++public class ShowRemainTimeUpdateEvent { ++ public ShowRemainTimeUpdateEvent() { ++ ++ } ++}","I think it would be better to use an `ItemUpdatedEvent` like for the ""prefer streaming"" preference. We already have a ton of events that need to be handled in all list fragments that just do the same everywhere. I think we could even remove some of the existing events in the future." +1612,"@@ -0,0 +1,17 @@ ++class AddSlugToProducts < ActiveRecord::Migration ++ def change ++ add_column :products, :slug, :string, null: true ++ ++ products = select_all(""select id, name from products"") ++ products.each do |product| ++ update(<<-SQL) ++ UPDATE products ++ SET slug='#{product[""name""].parameterize}' ++ WHERE id=#{product[""id""]} ++ SQL ++ end ++ ++ change_column_null :products, :slug, false ++ add_index :products, :slug, unique: true ++ end ++end",I think we have to manually write a down for this migration. +1613,"@@ -454,14 +454,13 @@ class _InternalFrame(object): + assert isinstance(sdf, spark.DataFrame) + + if index_map is None: +- # Here is when Koalas DataFrame is created directly from Spark DataFrame. +- assert not any(SPARK_INDEX_NAME_PATTERN.match(name) for name in sdf.schema.names), \ ++ assert not any(SPARK_INDEX_NAME_PATTERN.match(name) for name in sdf.columns), \ + ""Index columns should not appear in columns of the Spark DataFrame. Avoid "" \ +- ""index colum names [%s]."" % SPARK_INDEX_NAME_PATTERN ++ ""index column names [%s]."" % SPARK_INDEX_NAME_PATTERN + + # Create default index. +- index_map = [(SPARK_INDEX_NAME_FORMAT(0), None)] +- sdf = _InternalFrame.attach_default_index(sdf) ++ sdf, index_column = _InternalFrame.attach_default_index(sdf) ++ index_map = [(index_column, None)] + + if NATURAL_ORDER_COLUMN_NAME not in sdf.columns: + sdf = sdf.withColumn(NATURAL_ORDER_COLUMN_NAME, F.monotonically_increasing_id())","I don't think we still need this check, but I'd leave it as an assertion for now." +1614,"@@ -203,4 +203,9 @@ class Cart < ActiveRecord::Base + 0.0 + end + end ++ ++ # may be replaced with paper-trail or similar at some point ++ def version ++ self.updated_at.to_i ++ end + end","Since this may be the case, wondering if we should call the param `updated_at_i` or something so that we don't run into a problem distinguishing them down the road?" +1615,"@@ -215,6 +215,10 @@ namespace ScenarioMeasurement + } + TraceEventSession.Merge(files.ToArray(), traceFileName); + ++ if (guiApp) ++ { ++ appExe = Path.Join(workingDir, appExe); ++ } + string commandLine = $""\""{appExe}\""""; + if (!String.IsNullOrEmpty(appArgs)) + {",wondering why we need to join the paths here; seems evt.commandLine only takes whatever appExe is +1616,"@@ -329,8 +329,14 @@ public class ConfigCenterClient { + + public void refreshConfig(String configcenter, boolean wait) { + CountDownLatch latch = new CountDownLatch(1); ++ String encodeServiceName = """"; ++ try { ++ encodeServiceName = URLEncoder.encode(StringUtils.deleteWhitespace(serviceName), ""UTF-8""); ++ } catch (UnsupportedEncodingException e) { ++ LOGGER.error(""encode error: {}"",e.getMessage()); ++ } ++ String path = URIConst.ITEMS + ""?dimensionsInfo="" + encodeServiceName; + clientMgr.findThreadBindClientPool().runOnContext(client -> { +- String path = URIConst.ITEMS + ""?dimensionsInfo="" + StringUtils.deleteWhitespace(serviceName); + IpPort ipPort = NetUtils.parseIpPortFromURI(configcenter); + HttpClientRequest request = client.get(ipPort.getPort(), ipPort.getHostOrIp(), path, rsp -> { + if (rsp.statusCode() == HttpResponseStatus.OK.code()) {","1.not format code 2.failed but still continue? 3.""UTF-8"" can changed to java.nio.charset.StandardCharsets.UTF_8.name()" +1617,"@@ -74,6 +74,7 @@ from typing import Any, Callable, Iterator, List, Optional, Pattern, Tuple + import astroid + import astroid.exceptions + from astroid import bases, nodes ++from astroid.brain import brain_dataclasses + + from pylint.checkers import BaseChecker, utils + from pylint.checkers.utils import (","I'm wondering if we should add this to a `utils` module in `astroid`. Porting the util to `pylint` doesn't make sense as we would need to duplicate the globals that are being used in the function, but importing from `brain` also feels weird. @Pierre-Sassoulas Do you have an opinion?" +1618,"@@ -54,6 +54,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http + + InitializeHeaders(); + ++ if (_corruptedRequest) ++ { ++ await ProduceEnd(); ++ return; ++ } ++ + while (!_requestProcessingStopping && !TakeMessageHeaders(SocketInput, FrameRequestHeaders)) + { + if (SocketInput.RemoteIntakeFin)",This seems different than what we do for corrupted request headers. I would like to determine the correct behavior and consolidate this logic. +1619,"@@ -292,7 +292,7 @@ class _RunData(object): + direct_access_sources = set() + for backend in backend_service.backends: + instance_group = self.find_instance_group_by_url( +- backend.get('group')) ++ backend.get('resourceGroup')) + if not instance_group: + continue + ","Please make the change in the CAI inventory, rather than changing the scanner." +1620,"@@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.jsp.ast; + + import net.sourceforge.pmd.lang.ast.AbstractNode; + +-public class AbstractJspNode extends AbstractNode implements JspNode { ++public abstract class AbstractJspNode extends AbstractNode implements JspNode { + + protected JspParser parser; + ","adding this `abstract` is a breaking API change. Even though I agree it makes perfect sense to have it, we can't break this API until PMD 7.0.0. We should revert this particular change. We could make a reminder ticket like we did with #463 for 6.0.0" +1621,"@@ -16,6 +16,7 @@ describe IndividualPlan do + + it_behaves_like 'a Plan with countable subscriptions' + it_behaves_like 'a Plan for public listing' ++ it_behaves_like 'Purchaseable plan' + + describe '.active' do + it 'only includes active plans' do","This is following the existing convention, but I'm not sure the convention is a good one. I think it would be better to have one shared example group: - It means we don't need to add new example groups twice every time. - If the shared example group looks large, that makes it more obvious that our team models have too much shared behavior. I don't want to do anything about this right now (I'm pretty sure I can wipe out this shared example group when I change team plans), but it's good to keep in mind." +1622,"@@ -304,14 +304,15 @@ size_t network_prefix) + bool nano::server_socket::limit_reached_for_incoming_subnetwork_connections (std::shared_ptr const & new_connection) + { + debug_assert (strand.running_in_this_thread ()); +- if (node.flags.disable_max_peers_per_subnetwork) ++ if (node.flags.disable_max_peers_per_subnetwork || nano::transport::is_ipv4_or_v4_mapped_address (new_connection->remote.address ())) + { + // If the limit is disabled, then it is unreachable. ++ // If the address is IPv4 we don't check for a network limit, since its address space isn't big as IPv6 /64. + return false; + } + auto const counted_connections = socket_functions::count_subnetwork_connections ( + connections_per_address, +- nano::transport::mapped_from_v4_or_v6 (new_connection->remote.address ()), ++ new_connection->remote.address ().to_v6 (), + node.network_params.network.ipv6_subnetwork_prefix_for_limiting); + return counted_connections >= node.network_params.network.max_peers_per_subnetwork; + }",I do not think we need to do a source code change to handle this. We could set the subnetwork to default to /32 (/128 for ipv6 ipv4-mapped) +1623,"@@ -41,7 +41,7 @@ gboolean + ot_remote_builtin_delete_cookie (int argc, char **argv, GCancellable *cancellable, GError **error) + { + g_autoptr(OstreeRepo) repo = NULL; +- g_autoptr(GOptionContext) context = g_option_context_new (""NAME DOMAIN PATH COOKIE_NAME- Remote one cookie from remote""); ++ g_autoptr(GOptionContext) context = g_option_context_new (""NAME DOMAIN PATH COOKIE_NAME- Remove one cookie from remote""); + + if (!ostree_option_context_parse (context, option_entries, &argc, &argv, + OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error))",It looks good overall! The only issue I have is that the description string is now duplicated twice right? Once in the struct and once in the parameter string? Maybe let's pass the struct to the command so that `ostree_option_context_parse` can set it as the summary? Similar to what we do in rpm-ostree. +1624,"@@ -29,7 +29,7 @@ import org.openqa.selenium.remote.service.DriverService; + * + * @see List of ChromeWebdriver commands + */ +-class ChromeDriverCommandExecutor extends DriverCommandExecutor { ++public class ChromeDriverCommandExecutor extends DriverCommandExecutor { + + private static final ImmutableMap CHROME_COMMAND_NAME_TO_URL = ImmutableMap.of( + ChromeDriverCommand.LAUNCH_APP,",This states very clearly that this is a derivative of Chrome and not Chromium. Do we need to extract an abstract `ChromiumCommandExecutor` and have both Edge and Chrome derive from that? +1625,"@@ -84,7 +84,9 @@ public class CompareObjectsWithEqualsRule extends AbstractJavaRule { + ASTReferenceType type1 = ((Node) nd1.getAccessNodeParent()) + .getFirstDescendantOfType(ASTReferenceType.class); + // skip, if it is an enum +- if (type0.getType() != null && type0.getType().equals(type1.getType()) && type0.getType().isEnum()) { ++ if (type0.getType() != null && type0.getType().equals(type1.getType()) ++ // It may be a custom enum class or an explicit Enum class usage ++ && (type0.getType().isEnum() || type0.getType() == java.lang.Enum.class)) { + return data; + } + ","it seems to me, the issue lies on `isEnum()` itself, returning false for something that is an enum. I'd rather change it there than here." +1626,"@@ -49,6 +49,15 @@ class QuteSchemeHandler(schemehandler.SchemeHandler): + + """"""Scheme handler for qute: URLs."""""" + ++ handlers = dict() ++ ++ @classmethod ++ def addHandler(cls, name): ++ """"""Add a handler to the qute: sheme."""""" ++ def namedecorator(function): ++ cls.handlers[name] = function ++ return namedecorator ++ + def createRequest(self, _op, request, _outgoing_data): + """"""Create a new request. + ",Please use `{}` instead of `dict()` +1627,"@@ -20,11 +20,12 @@ + * External dependencies + */ + import PropTypes from 'prop-types'; ++import { useInView } from 'react-intersection-observer'; + + /** + * WordPress dependencies + */ +-import { useCallback } from '@wordpress/element'; ++import { useCallback, useEffect } from '@wordpress/element'; + import { __ } from '@wordpress/i18n'; + + /**",I have concerns about using this in more places before #3278 - I'll take a look at that again shortly. +1628,"@@ -37,7 +37,16 @@ func TestConvert(t *testing.T) { + testLog := newTestLog() + testLog.Topics = topics + testLog.NotFixTopicCopyBug = true +- receipt := &Receipt{1, 1, hash.ZeroHash256, 1, ""test"", []*Log{testLog}, nil, ""balance not enough""} ++ receipt := &Receipt{ ++ Status: 1, ++ BlockHeight: 1, ++ ActionHash: hash.ZeroHash256, ++ GasConsumed: 1, ++ ContractAddress: ""test"", ++ TxIndex: 1, ++ logs: []*Log{testLog}, ++ executionRevertMsg: ""balance not enough"", ++ } + + typeReceipt := receipt.ConvertToReceiptPb() + require.NotNil(typeReceipt)",new field needs to be asserted +1629,"@@ -190,6 +190,7 @@ void Host::appendLogsInternal(folly::EventBase* eb, + { + std::lock_guard g(self->lock_); + self->setResponse(r); ++ self->lastLogIdSent_ = self->logIdToSend_; + } + self->noMoreRequestCV_.notify_all(); + return;","when send log failed, why update the last sent log id?" +1630,"@@ -127,12 +127,12 @@ public final class Tuple0 implements Tuple, Comparable, Serializable { + } + + @Override +- public Tuple1 prepend(T value) { ++ public Tuple1 append(T value) { + return new Tuple1<>(value); + } + + @Override +- public Tuple1 append(T value) { ++ public Tuple1 prepend(T value) { + return new Tuple1<>(value); + } + ","what was the problem with the previous order? `prepend` comes conceptually before `append`, i.e. `insert before` should be before `insert after`, I think" +1631,"@@ -291,6 +291,8 @@ type BackupInfo struct { + // Timestamp is the timestamp at which the source volume + // was backed up to cloud + Timestamp time.Time ++ // Metadata associated with the backup ++ Metadata map[string]string + // Status indicates if this backup was successful + Status string + }",Why is this necessary? Could you provide some context? +1632,"@@ -46,7 +46,9 @@ public class HTMLTestResults { + private final HTMLSuiteResult suite; + + private static final String HEADER = ""\n"" + +- "" ++ ++ ++ ++ ","1. I don’t think both promise files are needed, we used to recommend just `es6-promise.auto.min.js`, and I think it worked in our tests: https://github.com/transloadit/uppy/pull/1576/files. I could be wrong. +2. We have these polyfills included in the website examples, like https://uppy.io/examples/dashboard/. Maybe that’s enough for testing, and we could keep `dev` smaller/faster? On the one hand, it’s not too big of an addition, on the other it’s external resources just for IE testing.",2019-06-13 11:33:53 +187,"@@ -35,7 +35,7 @@ A site-wide unique ID for the instance. + If multiple Uppy instances are being used, for example on two different pages, an `id` should be specified. + This allows Uppy to store information in `localStorage` without colliding with other Uppy instances. + +-Note that this ID should be persistent across page reloads and navigation—it shouldn't be a random number that's different every time Uppy is loaded. ++Note that this ID should be persistent across page reloads and navigation — it shouldn't be a random number that's different every time Uppy is loaded.","IIRC em dashes do not require spaces around them, do they?",2018-01-02 11:36:39 +37,"@@ -353,6 +354,30 @@ function findDOMElement (element) { + } + } + ++function getSocketHost (url) { ++ // get the host domain ++ var regex = /^(?:https?:\/\/|\/\/)?(?:[^@\n]+@)?(?:www\.)?([^\n]+)/ ++ var host = regex.exec(url)[1] ++ var socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws' ++ ++ return `${socketProtocol}://${host}` ++} ++ ++function _emitSocketProgress (uppyInstance, progressData, file) {","Can you rename `uppyInstance` to something like `uploader`? I think that's a bit clearer, I thought it was referring to a `Core` instance first.",2017-05-26 10:40:46 +234,"@@ -355,7 +355,8 @@ describe('src/Core', () => { + }) + .then(() => { + const fileId = Object.keys(core.state.files)[0] +- core.emit('preprocess-progress', fileId, { ++ const file = core.state.files[fileId]",`core.getFile(fileId)`?,2018-02-22 14:28:03 +544,"@@ -358,14 +358,14 @@ module.exports = class ProviderView { + state = this.plugin.getPluginState() + state.selectedFolders[folderId] = { loading: false, files: files } + this.plugin.setPluginState({ selectedFolders: folders }) +- const dashboard = this.plugin.uppy.getPlugin('Dashboard')","I think we have to keep this as a fallback for now, else it's a small breaking change :(",2019-07-08 09:46:31 +382,"@@ -36,6 +36,12 @@ In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` gl + const GoogleDrive = Uppy.GoogleDrive + ``` + ++## CSS ++ ++Dashboard plugin is recommended as a container to all Provider plugins, including Google Drive. If you are using Dashboard, it [comes with all the nessesary styles](/docs/dashboard/#CSS) for Dropbox as well. ++ ++⚠️ If you are feeling adventerous, and want to use Google Drive plugin separately, without Dashboard, make sure to include `@uppy/provider-views/dist/style.css` (or `style.min.css`) CSS file. This is experimental, not officialy supported and not recommened.",:point_up: ,2018-11-29 12:44:02 +381,"@@ -36,6 +36,13 @@ In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` gl + const Dropbox = Uppy.Dropbox + ``` + ++## CSS ++ ++Dashboard plugin is recommended as a container to all Provider plugins, including Dropbox. If you are using Dashboard, it [comes with all the nessesary styles](/docs/dashboard/#CSS) for Dropbox as well. ++ ++⚠️ If you are feeling adventerous, and want to use Dropbox plugin separately, without Dashboard, make sure to include `@uppy/provider-views/dist/style.css` (or `style.min.css`) CSS file. This is experimental, not officialy supported and not recommened.","adventerous → adventurous +recommened → recommended + +Same in a few other places:",2018-11-29 12:43:49 +376,"@@ -36,6 +36,17 @@ In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` gl + const Url = Uppy.Url + ``` + ++## CSS ++ ++The `@uppy/url` plugin requires the following CSS for styling: ++ ++```js ++import '@uppy/core/dist/style.css' ++import '@uppy/url/dist/style.css' ++``` ++ ++Import general Core styles from `@uppy/core/dist/style.css` first, then add the Informer styles from `@uppy/url/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system.","```suggestion +Import general Core styles from `@uppy/core/dist/style.css` first, then add the Url styles from `@uppy/url/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. +```",2018-11-22 12:26:19 +375,"@@ -36,6 +36,17 @@ In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` gl + const Webcam = Uppy.Webcam + ``` + ++## CSS ++ ++The `@uppy/webcam` plugin requires the following CSS for styling: ++ ++```js ++import '@uppy/core/dist/style.css' ++import '@uppy/webcam/dist/style.css' ++``` ++ ++Import general Core styles from `@uppy/core/dist/style.css` first, then add the Informer styles from `@uppy/webcam/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system.","some plugin docs refer to Informer instead of the actual plugin name + +```suggestion +Import general Core styles from `@uppy/core/dist/style.css` first, then add the Webcam styles from `@uppy/webcam/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. +```",2018-11-22 12:26:04 +14,"@@ -36,61 +36,65 @@ Returns current state. + + #### setState({itemToUpdate: data}) + +-Updates state with new state (Object.assign({}, this.state, newState)) and runs `updateAll()`. ++Updates state with new state (Object.assign({}, this.state, newState)) and then runs `updateAll()`. + + #### updateAll() + +-Iterates over all `plugins` and runs `update` on each of them. ++Iterates over all `plugins` and runs `update()` on each of them. + + #### updateMeta(data, fileID) + +-Given `{size: 1200}` adds that metadata to a file. ++Given `{ size: 1200 }` adds that metadata to a file. + + #### addFile(file) + +-Adds a new file to `state`, method used by `acquirer` plugins like Drag & Drop and Google Drive, +-or can be called by the user on uppy instance directly. ++Adds a new file to `state`. This method is used by `acquirer` plugins like Drag & Drop, Webcam and Google Drive, ++or can be called by the user on uppy instance directly: `uppy.addFile(myFile)`. + +-Normalizes that file: tries to figure out file type by extension if mime is missing, use noname if name is missing and so on. ++Normalizes that file too: tries to figure out file type by extension if mime is missing, use noname if name is missing, sets progress: 0 and so on. + + #### removeFile(fileID) + + Removes file from `state`. + + #### addThumbnail(fileID) + +-Reads image from file’s data object in base64 and resizes that, using canvas. Then `state` is updated with a file that has thumbnail it it. Thumbnails are used for file previews by plugins like Dashboard. ++Reads image from file’s data object in base64 and resizes that, using canvas. Then `state` is updated with a file that has thumbnail in it. Thumbnails are used for file previews by plugins like Dashboard. + + #### state.capabilities + +-Core (or plugins) check and set capabilities, like: `resumable: true`, `touch: false`, `dragdrop: true` that could possibly be used by all plugins. ++Core (or plugins) check and set capabilities, like: `resumable: true` (this is set by Tus Plugin), `touch: false`, `dragdrop: true`, that could possibly be used by all plugins. + + #### log(msg) + + Logs stuff to console only if user specified `debug: true`, silent in production. + + #### core.on('event', action), core.emit('event'), core.emitter + +-An event emitter embedded into Core that is passed to plugins and can be used directly on the instance. Event emitter is used for plugins to communicate with other plugins and Core. ++An event emitter embedded into Core that is passed to Plugins, and can be used directly on the instance. Used by Plugins for communicating with other Plugins and Core. + + For example: + +-- Core listens for `core:upload-progress` event and calculates speed and ETA for one file, that the event was about, and for all files currently in progress. ++- Core listens for `core:upload-progress` event and calculates speed & ETA for all files currently in progress. *Uploader plugins could just call core.updateProgress().* + - Core checks if browser in offline or online and emits `core:is-offline` or `core:is-online` that other plugins can listen to. +-- Any plugin can emit `informer` event that `Informer` plugin can use to display info bubbles. Currently only used in the Dashboard plugin. Example: `core.emitter.emit('informer', 'Connected!', 'success', 3000)`. (Should this be a Core method instead of plugin?). +-- Uploader plugins listen to `core:upload` event (can be emitted after a file has been added or when upload button has been pressed), get files via `core.getState().files`, filter those that are not marked as complete and upload them, emitting progress events. ++- Any plugin can emit `informer` event that `Informer` plugin can use to display info bubbles. Currently only used in the Dashboard plugin. Example: `core.emitter.emit('informer', 'Connected!', 'success', 3000)`. (Should this be a Core method instead of Plugin?). *Could be replaced by core.inform(info) method that will just update state with info.* ++- Uploader plugins listen to `core:upload` event (can be emitted after a file has been added or when upload button has been pressed), get files via `core.getState().files`, filter those that are not marked as complete and upload them, emitting progress events. *This could be replaced by core.upload() method that will loop through all `uploaders` and run `upload()` on them, or we could only allow one uploader.* ++ ++*Should most or all of the events from the above be replaced with method calls? Should event-emitter be used for internal communication or just for the user to hook on to, like `uppy.on(core:upload:complete, doStuff)`? Right now its both, same event-emitter serves as a communication bus inside Uppy + its exposed to the user outside. Inspiration for using it as a bus came from Substack’s example here https://github.com/substack/training/blob/3041b1e4e3908d4df1b26cf578c34cd4df8fe9b7/web-dev-whirlwind/example/arch/bus/actions.js, and somewhat from Redux and Choo’s send https://github.com/yoshuawuyts/choo/#views.* + + *See discussion about Core and Event Emitter: https://github.com/transloadit/uppy/issues/116#issuecomment-247695921* + + ## Plugins + +-Plugins extend the functionality of Core (which itself is very much barebones, does almost nothing). ++Plugins extend the functionality of Core (which itself is very much barebones, does almost nothing). Plugins actually do the work — select files, modify and upload them, and show the UI. ++ ++Plugins that have some UI can be mounted anywhere in the dom. With current design you can have a Drag & Drop area in `#dragdrop` and Progressbar in `body`. Plugins can also be mounted into other plugins that support that, like Dashboard. + +-Each plugin extends `Plugin` class with default methods that can be overwritten: ++Each plugin extends `Plugin` class with default methods that can be overridden: + + #### update() + +-Gets called when state is changes and `updateAll()` is called from Core. Checks if a DOM element (tree) has been created with a reference for it stored in plugin’s `this.el`. If so, crates a new element (tree) `const newEl = this.render(currentState)` on current plugin and then calls `yo.update(this.el, newEl)` to effectively update the existing element to match the new one (morphdom is behind that). ++Gets called when state changes and `updateAll()` is called from Core. Checks if a DOM element (tree) has been created with a reference for it stored in plugin’s `this.el`. If so, crates a new element (tree) `const newEl = this.render(currentState)` for current plugin and then calls `yo.update(this.el, newEl)` to effectively update the existing element to match the new one (morphdom is behind that).","crates-> creates +",2016-10-13 09:49:15 +458,"@@ -36,7 +29,8 @@ class UrlUI extends Component { + aria-label={this.props.i18n('enterUrlToImport')} + placeholder={this.props.i18n('enterUrlToImport')} + onkeyup={this.handleKeyPress} +- ref={(input) => { this.input = input }} /> ++ ref={(input) => { this.input = input }} ++ data-uppy-super-focusable />",`ref={(input)` not needed here?,2019-05-03 18:28:28 +524,"@@ -36,7 +36,7 @@ function addDashboardPlugin (uppy, opts, overrideOpts) { + }) + + const inline = overrideOpts.inline == null ? dashboardOpts.inline : overrideOpts.inline +- if (inline === false) { ++ if (!inline) {",@arturi this is where we were checking it inside Robodog to determine whether modal options should be passed through,2019-06-24 14:07:00 +235,"@@ -361,8 +361,10 @@ data = { + ``` + + ```javascript +-uppy.on('upload-progress', (data) => {",the `data` object snippet still has an `id` up here—i think we can probably remove it entirely because you added the object shape in a comment in this code block.,2018-02-22 14:30:50 +640,"@@ -365,19 +366,27 @@ module.exports = class ThumbnailGenerator extends Plugin { + } + + install () { +- this.uppy.on('file-added', this.onFileAdded) + this.uppy.on('file-removed', this.onFileRemoved) +- this.uppy.on('restored', this.onRestored) ++ if (this.opts.lazy) { ++ this.uppy.on('thumbnail:request', this.onFileAdded)","When scrolling a list of non-image files, this results in queue events like this: + + + +Should we add `isPreviewSupported(file.type)` to `onFileAdded`?",2019-11-27 16:15:42 +691,"@@ -365,6 +382,23 @@ module.exports = class Webcam extends Plugin { + }, 1000) + } + ++ changeVideoSource (deviceId) { ++ this.stop() ++ this.start(deviceId) ++ } ++ ++ getVideoSources () { ++ this.videoSources = [] ++ this.mediaDevices.enumerateDevices().then(res => { ++ this.videoSources = [] ++ res.forEach((device) => {","We can do `this.videoSources = res.filter()` here, using [Array#filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter).",2020-03-09 09:55:59 +113,"@@ -367,7 +367,7 @@ function copyToClipboard (textToCopy, fallbackString) { + const magicCopyFailed = (err) => { + document.body.removeChild(textArea) + window.prompt(fallbackString, textToCopy) +- return reject('Oops, unable to copy displayed fallback prompt: ' + err) ++ return reject(new Error('Oops, unable to copy displayed fallback prompt: ' + err)) + }","> unable to copy displayed fallback prompt + +does this mean “unable to copy, so displayed fallback prompt instead”? :) should it reject if the prompt is successful shown?",2017-09-22 18:01:13 +782,"@@ -37,19 +37,6 @@ module.exports = class GoogleDrive extends Plugin { + this.view = new DriveProviderViews(this, { + provider: this.provider + }) +- // Set default state for Google Drive +- this.setPluginState({ +- authenticated: false, +- files: [], +- folders: [], +- directories: [], +- activeRow: -1, +- filterInput: '', +- isSearchVisible: false, +- hasTeamDrives: false, +- teamDrives: [], +- teamDriveId: ''","This teamDrive stuff is specific to gdrive, should it be kept so it's still initialised properly? Or added to the DriveProviderViews constructor maybe?",2020-06-15 13:05:23 +384,"@@ -37,3 +37,7 @@ uppy.use(Instagram, {target: Dashboard, serverUrl: 'http://localhost:3020'}) + const Url = require('@uppy/url') + uppy.use(Url, {target: Dashboard, serverUrl: 'http://localhost:3020'}) + ``` ++ ++⚠️ The [Dashboard](/docs/dashboard) plugin is recommended as a universal container to all Provider plugins. It also comes with file previews, progress reporting and more. If you are using the Dashboard, it already [comes with all the nessesary styles](/docs/dashboard/#CSS) and functionality for Providers to work well. ++ ++If you are feeling adventerous, you can technically use a Provider plugin separately, without the Dashboard. Make sure to then include `@uppy/provider-views/dist/style.css` (or `style.min.css`) CSS file. But this is experimental, not officialy supported and not recommened.",:point_up: ,2018-11-29 12:44:17 +996,"@@ -370,6 +370,7 @@ module.exports = class Webcam extends Plugin { + // eslint-disable-next-line compat/compat + recordedVideo: URL.createObjectURL(file.data), + }) ++ this.opts.mirror = false",Will this reset if you cancel and then re-record?,2021-04-01 22:26:01 +510,"@@ -370,8 +380,13 @@ module.exports = class XHRUpload extends Plugin { + files.forEach((file, i) => { + const opts = this.getOptions(file) + ++ // Set `file.data.type` in the blob to `file.meta.type`, ++ // because we might have detected a more accurate file type in Uppy ++ // https://stackoverflow.com/a/50875615 ++ file.data = file.data.slice(0, file.data.size, file.meta.type)","I would prefer doing `const data = file.data.slice()` here instead of mutating the object, state isn't supposed to be modified outside of setState() calls",2019-06-12 08:12:47 +682,"@@ -372,6 +372,9 @@ uppy.addFile({ + name: 'my-file.jpg', // file name + type: 'image/jpeg', // file type + data: blob, // file blob ++ meta: { ++ relativePath: string, // optional, determines the unique relative path to build the file uppy id","The file ID is kind of a detail. I think the important thing for end-users is that it allows you to add multiple identical files. Maybe we can do something like this? +```suggestion + // optional, store the directory path of a file so Uppy can tell identical files in different directories apart + relativePath: webkitFileSystemEntry.relativePath, +```",2020-03-02 14:04:06 +158,"@@ -379,24 +388,24 @@ module.exports = class DashboardUI extends Plugin { + .map(attachRenderFunctionToTarget) + + const startUpload = (ev) => { +- this.core.upload().catch((err) => { ++ this.uppy.upload().catch((err) => { + // Log error. +- this.core.log(err.stack || err.message || err) ++ this.uppy.log(err.stack || err.message || err) + }) + } + + const cancelUpload = (fileID) => { +- this.core.emit('core:upload-cancel', fileID) +- this.core.emit('core:file-remove', fileID) ++ this.uppy.emit('upload-cancel', fileID) ++ this.uppy.removeFile(fileID)",++ nice catch,2017-12-09 16:14:19 +377,"@@ -38,11 +38,16 @@ const StatusBar = Uppy.StatusBar + + ## CSS + +-The `@uppy/status-bar` plugin includes a CSS file for styling. If you are using the [`@uppy/dashboard`](/docs/dashboard) plugin, you do not need to include the styles for the StatusBar, because the Dashboard already includes it. ++The `@uppy/status-bar` plugin requires the following CSS for styling: + +-The CSS file lives at `@uppy/status-bar/dist/style.css`. A minified version can be found at `@uppy/status-bar/dist/style.min.css`. ++```js ++import '@uppy/core/dist/style.css' ++import '@uppy/status-bar/dist/style.css' ++``` ++ ++Import general Core styles from `@uppy/core/dist/style.css` first, then add the Informer styles from `@uppy/status-bar/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system.","```suggestion +Import general Core styles from `@uppy/core/dist/style.css` first, then add the Progress Bar styles from `@uppy/status-bar/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system. +```",2018-11-22 12:26:36 +383,"@@ -38,6 +38,12 @@ In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` gl + const Instagram = Uppy.Instagram + ``` + ++## CSS ++ ++Dashboard plugin is recommended as a container to all Provider plugins, including Instagram. If you are using Dashboard, it [comes with all the nessesary styles](/docs/dashboard/#CSS) for Dropbox as well. ++ ++⚠️ If you are feeling adventerous, and want to use Instagram plugin separately, without Dashboard, make sure to include `@uppy/provider-views/dist/style.css` (or `style.min.css`) CSS file. This is experimental, not officialy supported and not recommened.",:point_up: ,2018-11-29 12:44:09 +255,"@@ -381,6 +393,7 @@ class Uppy { + fileName = 'noname' + } + const fileExtension = Utils.getFileNameAndExtension(fileName).extension ++ console.log(fileExtension)",forgot to remove this?,2018-05-09 15:47:15 +566,"@@ -383,7 +383,50 @@ module.exports = class XHRUpload extends Plugin { + }).then((res) => { + const token = res.token + const host = getSocketHost(file.remote.companionUrl) +- const socket = new Socket({ target: `${host}/api/${token}` }) ++ const socket = new Socket({ target: `${host}/api/${token}`, autoOpen: false }) ++ ++ this.onFileRemove(file.id, () => { ++ socket.send('pause', {}) ++ queuedRequest.abort() ++ resolve(`upload ${file.id} was removed`) ++ }) ++ ++ this.onPause(file.id, (isPaused) => {","I thought xhr uploads can’t be pause-resumed? Or is this for `aws-s3-multipart` and such, that use xhr-upload?",2019-08-07 13:39:17 +162,"@@ -385,11 +386,37 @@ class Uppy { + } + + removeFile (fileID) { +- const updatedFiles = Object.assign({}, this.getState().files) ++ const { files, currentUploads } = this.state ++ const updatedFiles = Object.assign({}, files) + const removedFile = updatedFiles[fileID] + delete updatedFiles[fileID] + +- this.setState({files: updatedFiles}) ++ // Remove this file from its `currentUpload`. ++ const updatedUploads = Object.assign({}, currentUploads) ++ const removeUploads = [] ++ Object.keys(updatedUploads).forEach((uploadID) => { ++ const newFileIDs = currentUploads[uploadID].fileIDs.filter((uploadFileID) => uploadFileID !== fileID) ++ // Remove the upload if no files are associated with it anymore. ++ if (newFileIDs.length === 0) { ++ removeUploads.push(uploadID) ++ return ++ } ++ ++ updatedUploads[uploadID] = Object.assign({}, currentUploads[uploadID], { ++ fileIDs: newFileIDs ++ }) ++ }) ++ ++ this.setState({ ++ currentUploads: updatedUploads, ++ files: updatedFiles ++ }) ++ ++ removeUploads.forEach((uploadID) => { ++ this.removeUpload(uploadID) ++ }) ++ ++ this.calculateTotalProgress() + this._calculateTotalProgress()",Accidental duplicate `calculateTotalProgress` here.,2017-12-12 01:06:18 +478,"@@ -385,7 +389,15 @@ class Uploader { + const formData = Object.assign( + {}, + this.options.metadata, +- { [this.options.fieldname]: file } ++ { ++ [this.options.fieldname]: { ++ value: file, ++ options: { ++ filename: this.uploadFileName, ++ contentType: this.options.metadata.type ++ } ++ } ++ }","Maybe a comment/link here too, as to why `filename` and `contentType`? Stating that it’s conventional and linking to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#Directives and https://github.com/request/request?",2019-05-24 14:38:17 +796,"@@ -39,6 +39,37 @@ In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` gl + const GoogleDrive = Uppy.GoogleDrive + ``` + ++## Setting Up ++ ++To use the Google Drive provider, you need to configure the Google Drive keys that Companion should use. With the standalone Companion server, specify environment variables: ++```shell ++export COMPANION_GOOGLE_KEY=""Google Drive OAuth client ID"" ++export COMPANION_GOOGLE_SECRET=""Google Drive OAuth client secret"" ++``` ++ ++When using the Companion Node.js API, configure these options: ++```js ++companion.app({ ++ providerOptions: { ++ drive: { ++ key: 'Google Drive OAuth client ID', ++ secret: 'Google Drive OAuth client secret' ++ } ++ } ++}) ++``` ++ ++To sign up for API keys, go to the [Google Developer Console](https://console.developers.google.com/). ++ ++Create a project for your app if you don't have one yet. ++- On the project's dashboard, [enable the Google Drive API](https://developers.google.com/drive/api/v3/enable-drive-api). ++- [Set up OAuth authorization](https://developers.google.com/drive/api/v3/about-auth). Use this for an authorized redirect URI: ++ ``` ++ https://$YOUR_COMPANION_HOST_NAME/connect/drive/callback","```suggestion + https://$YOUR_COMPANION_HOST_NAME/connect/google/callback +``` +Another inconsistency that we should fix as per [this](https://github.com/transloadit/uppy/pull/2346#issuecomment-651096963)",2020-06-29 13:10:02 +667,"@@ -39,6 +46,19 @@ module.exports = function getIconByMime (fileType) { + } + } + ++ if (fileTypeGeneral === 'application' && ( ++ fileTypeSpecific === 'zip' || ++ fileTypeSpecific === 'x-7z-compressed' || ++ fileTypeSpecific === 'x-rar-compressed' || ++ fileTypeSpecific === 'x-gtar' || ++ fileTypeSpecific === 'x-apple-diskimage')","@goto-bus-stop do you maybe have better ideas on detecting archives? I could move the `fileTypeSpecific`s to an array, but other than that :)",2020-01-16 18:54:57 +798,"@@ -390,13 +391,48 @@ To work well with Companion, the **Module** must be a class with the following m + - token - authorization token (retrieved from oauth process) to send along with your request + - directory - the `id/name` of the directory from which data is to be retrieved. This may be ignored if it doesn't apply to your provider + - query - expressjs query params object received by the server (just in case there is some data you need in there). +- - `done (err, response, body)` - the callback that should be called when the request to your provider is made. As the signature indicates, the following data should be passed along to the callback `err`, `response`, and `body`. +-2. `download (options, onData, onResponse)` - downloads a particular file from the provider. ++ - `done (err, data)` - the callback that should be called when the request to your provider is made. As the signature indicates, the following data should be passed along to the callback `err`, and [`data`]((#list-data)). ++2. `download (options, onData)` - downloads a particular file from the provider. + - `options` - is an object containing the following attributes: + - token - authorization token (retrieved from oauth process) to send along with your request. + - id - ID of the file being downloaded. +- - `onData (chunk)` - a callback that should be called with each data chunk received on download. This is useful if the size of the downloaded file can be pre-determined. This would allow for pipelined upload of the file (to the desired destination), while the download is still going on. +- - `onResponse (response)` - if the size of the downloaded file can not be pre-determined by Companion, then this callback should be called in place of the `onData` callback. This callback would be called after the download is done, and would take the downloaded data (response) as the argument. ++ - query - expressjs query params object received by the server (just in case there is some data you need in there). ++ - `onData (err, chunk)` - a callback that should be called with each data chunk received as download is happening. The `err` argument is an error that should be passed if an error occurs during download. It should be `null` if there's no error. Once the download is completed and there are no more chunks to receive, `onData` should be called with `null` values like so `onData(null, null)` ++3. `size (options, done)` - returns the byte size of the file that needs to be downloaded. ++ - `options` - is an object containing the following attributes: ++ - token - authorization token (retrieved from oauth process) to send along with your request. ++ - id - ID of the file being downloaded. ++ - `done (err, size)` - the callback that should be called after the request to your provider is completed. As the signature indicates, the following data should be passed along to the callback `err`, and `size` (number). ++ ++The class must also have an `authProvider` string (lowercased) field which typically indicates the name of the provider (e.g ""dropbox""). ++ ++#### list data ++ ++```js ++{ ++ username: 'username or email of the user whose provider account is being accessed',","Some of these properties have example data and some have an explanation string, maybe it would be better to consistently use comments for explanation and example values as the values? some of the text gets quite long and with comments we can add some newlines :)",2020-06-29 13:39:48 +418,"@@ -392,7 +394,7 @@ + .uppy-ProviderBrowserItem-checkbox { + position: relative; + display: inline-block; +- top: -3px; ++ // top: -3px;",probably better to delete since we are now approaching `1.0`,2019-03-28 00:59:24 +141,"@@ -394,7 +395,7 @@ class Uppy { + */ + generatePreview (file) { + if (Utils.isPreviewSupported(file.type) && !file.isRemote) { +- Utils.createThumbnail(file, 200).then((thumbnail) => { ++ Utils.createThumbnail(file, 200, this.opts.thumbnailGeneration).then((thumbnail) => {","I wonder if it would be better to do the `this.opts.thumbnailGeneration` check here instead of changing `createThumbnail`? You probably wanted to keep it clean with the promise, maybe that’s a good idea.",2017-11-23 18:37:30 +390,"@@ -395,9 +393,13 @@ module.exports = class XHRUpload extends Plugin { + timer.done() + + if (ev.target.status >= 200 && ev.target.status < 300) { +- const resp = this.opts.getResponseData(xhr.responseText, xhr) ++ const body = this.opts.getResponseData(xhr.responseText, xhr) ++ const uploadResp = { ++ status: ev.target.status, ++ body ++ }",No `uploadURL` for bundles?,2018-12-19 20:22:39 +933,"@@ -4,6 +4,7 @@ const Uppy = require('@uppy/core') + const Dashboard = require('@uppy/dashboard') + const GoogleDrive = require('@uppy/google-drive') + const Dropbox = require('@uppy/dropbox') ++const Box = require('@uppy/box')","excluding from examples in the meantime +```suggestion +```",2020-11-13 09:14:29 +82,"@@ -4,8 +4,8 @@ + + + --> +-
  • "">Guide
  • +-
  • "">API
  • ",Can haz redirects for poor internetters stumbling upon `/api/`?,2017-08-14 12:14:02 +278,"@@ -40,54 +48,15 @@ uppy.use(Dashboard, { + disablePageScrollWhenModalOpen: true, + proudlyDisplayPoweredByUppy: true, + onRequestCloseModal: () => this.closeModal(), +- locale: { +- strings: { +- selectToUpload: 'Select files to upload', +- closeModal: 'Close Modal', +- upload: 'Upload', +- importFrom: 'Import from', +- dashboardWindowTitle: 'Uppy Dashboard Window (Press escape to close)', +- dashboardTitle: 'Uppy Dashboard', +- copyLinkToClipboardSuccess: 'Link copied to clipboard.', +- copyLinkToClipboardFallback: 'Copy the URL below', +- copyLink: 'Copy link', +- fileSource: 'File source', +- done: 'Done', +- name: 'Name', +- removeFile: 'Remove file', +- editFile: 'Edit file', +- editing: 'Editing', +- finishEditingFile: 'Finish editing file', +- localDisk: 'Local Disk', +- myDevice: 'My Device', +- dropPasteImport: 'Drop files here, paste, import from one of the locations above or', +- dropPaste: 'Drop files here, paste or', +- browse: 'browse', +- fileProgress: 'File progress: upload speed and ETA', +- numberOfSelectedFiles: 'Number of selected files', +- uploadAllNewFiles: 'Upload all new files', +- emptyFolderAdded: 'No files were added from empty folder', +- uploadComplete: 'Upload complete', +- resumeUpload: 'Resume upload', +- pauseUpload: 'Pause upload', +- retryUpload: 'Retry upload', +- uploadXFiles: { +- 0: 'Upload %{smart_count} file', +- 1: 'Upload %{smart_count} files' +- }, +- uploadXNewFiles: { +- 0: 'Upload +%{smart_count} file', +- 1: 'Upload +%{smart_count} files' +- }, +- folderAdded: { +- 0: 'Added %{smart_count} file from %{folder}', +- 1: 'Added %{smart_count} files from %{folder}' +- } +- } +- } ++ locale: {} + }) + ``` + ++### `id: 'Dashboard'` ++ ++A unique identifier for this Dashboard. Defaults to `'Dashboard'`. Change this if you need multiple Dashboard instances. ++Plugins that are added by the Dashboard get unique IDs based on this ID, like `'Dashboard:StatusBar'` and `'Dashboard:Informer'`. ++",💯,2018-05-24 22:56:56 +454,"@@ -40,6 +41,7 @@ + ""eslint-plugin-jest"": ""^21.27.2"", + ""eslint-plugin-node"": ""^4.2.3"", + ""eslint-plugin-promise"": ""^3.8.0"", ++ ""eslint-plugin-react"": ""^7.12.4"", + ""eslint-plugin-standard"": ""^3.1.0"",",do we need `eslint-plugin-react` for something?,2019-04-25 10:51:48 +227,"@@ -40,6 +41,8 @@ class MusicUploadButton extends React.Component { + } + + render () { ++ this.props.uppy.use(Webcam, { id: ""Webcam"" }); ++","Webcam will get `id: ""Webcam""` by default, so I’m wondering if we should omit this here for simplicity.",2018-02-15 00:35:04 +63,"@@ -401,6 +401,27 @@ function findDOMElement (element) { + } + } + ++/** ++* Get metadata object from a form element ++* ++* @param {Node|string} element ++* @return {Object|null} ++*/ ++ ++function getMetaFromForm (element) { ++ if (!element || element.tagName !== 'FORM') { ++ console.error('Metadata can only be extracted from form elements') ++ return null ++ } ++ ++ var formData = new FormData(element) ++ var result = {} ++ for (var entry of formData.entries()) {",`entries()` is not supported in IE and Edge…but it looks like there isn't really another way to get data out of a FormData instance 😕 Maybe there's a library for that that doesn't use `FormData`?,2017-06-29 11:30:41 +345,"@@ -401,6 +401,6 @@ class Uploader { + + Uploader.FILE_NAME_PREFIX = 'uppy-file' + // @todo do a proper migration to change this name +-Uploader.STORAGE_PREFIX = 'uppy-server' ++Uploader.STORAGE_PREFIX = 'companion'",Do we need a proper migration to change this name as the comment says? :smile: I think this is only for temporary storage so it may not be a big deal…,2018-09-03 12:00:04 +103,"@@ -402,8 +402,9 @@ describe('src/Core', () => { + .then(() => core.upload()) + .then(() => { + expect(postprocessor1.mock.calls.length).toEqual(1) +- const lastModifiedTime = new Date() +- const fileId = 'foojpg' + lastModifiedTime.getTime() ++ // const lastModifiedTime = new Date() ++ // const fileId = 'foojpg' + lastModifiedTime.getTime()",Could remove these lines entirely :) ,2017-09-11 07:50:13 +268,"@@ -407,23 +416,28 @@ module.exports = class Tus extends Plugin { + } + + uploadFiles (files) { +- const promises = files.map((file, index) => { +- const current = parseInt(index, 10) + 1 ++ const actions = files.map((file, i) => { ++ const current = parseInt(i, 10) + 1 + const total = files.length + + if (file.error) { +- return Promise.reject(new Error(file.error)) +- } +- +- this.uppy.log(`uploading ${current} of ${total}`) +- +- if (file.isRemote) { +- return this.uploadRemote(file, current, total) ++ return () => Promise.reject(new Error(file.error)) ++ } else if (file.isRemote) { ++ // We emit upload-started here, so that it's also emitted for files ++ // that have to wait due to the `limit` option. ++ this.uppy.emit('upload-started', file)",The `upload-started` events on lines 207 and 230 need to be removed because they were moved here,2018-05-14 11:24:41 +506,"@@ -41,11 +45,12 @@ exports.debug = (msg, tag) => { + * @param {string | Error} msg the message to log + * @param {string} tag a unique tag to easily search for this message + * @param {string} level error | info | debug ++ * @param {function=} color function to display the log in appropriate color + */ +-const log = (msg, tag, level) => { +- // @TODO add some colors based on log level ++const log = (msg, tag, level, color) => { + const time = new Date().toISOString() ++ color = color || ((message) => message) + // exclude msg from template string so values such as error objects + // can be well formatted +- console.log(`uppy: ${time} [${level}] ${tag || ''}`, msg) ++ console.log(color(`uppy: ${time} [${level}] ${tag || ''}`), color(msg))",Should this read `companion: ` actually?,2019-06-11 07:57:16 +202,"@@ -41,19 +41,19 @@ $ npm install uppy + + We recommend installing from NPM and then using a module bundler such as [Webpack](http://webpack.github.io/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). + +-If you like, you can also use a pre-built bundle, for example from [unpkg CDN](https://unpkg.com/uppy/). In that case `Uppy` will attach itself to the global `window.Uppy` object. ++Alternatively, you can also use a pre-built bundle, for example from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object.","We could just get rid of the ""for example"" bit here I think. + +> Alternatively, you can use a pre-built bundle from Transloadit's CDN: Edgly.",2018-01-29 08:53:19 +313,"@@ -41,57 +41,9 @@ function buildUppyBundle (minify) { + }) + } + +-// function copyLocales () { +-// var copyCommand = 'cp -R ' + path.join(srcPath, 'locales/') + ' ' + path.join(distPath, 'locales/') +-// return new Promise(function (resolve, reject) { +-// exec(copyCommand, function (error, stdout, stderr) { +-// if (error) { +-// handleErr(error) +-// reject(error) +-// return +-// } +-// console.info(chalk.green('✓ Copied locales to dist')) +-// resolve() +-// }) +-// }) +-// } +- +-// function buildLocale (file) { +-// return new Promise(function (resolve, reject) { +-// var fileName = path.basename(file, '.js') +-// browserify(file) +-// .transform(babelify) +-// .on('error', handleErr) +-// .bundle() +-// .pipe(fs.createWriteStream('./dist/locales/' + fileName + '.js', 'utf8')) +-// .on('error', handleErr) +-// .on('finish', function () { +-// console.info(chalk.green('✓ Built Locale:'), chalk.magenta(fileName + '.js')) +-// resolve() +-// }) +-// }) +-// } +- +-// function buildUppyLocales () { +-// mkdirp.sync('./dist/locales') +-// var localePromises = [] +-// glob('./src/locales/*.js', function (err, files) { +-// if (err) console.log(err) +-// files.forEach(function (file) { +-// localePromises.push(buildLocale(file)) +-// }) +-// }) +-// return Promise.all(localePromises) +-// } +- + mkdirp.sync(distPath) + + Promise.all([buildUppyBundle(), buildUppyBundle(true)]) + .then(function () { + console.info(chalk.yellow('✓ JS Bundle 🎉')) + }) +- +-// Promise.all([buildUppyBundle(), buildUppyBundle(true), buildUppyLocales()]) +-// .then(function () { +-// console.info(chalk.yellow('✓ JS Bundle 🎉')) +-// })","ha, good :)",2018-07-16 10:28:34 +374,"@@ -41,7 +41,7 @@ + ""express-interceptor"": ""^1.2.0"", + ""express-prom-bundle"": ""^3.1.0"", + ""express-session"": ""1.15.6"", +- ""grant-express"": ""^4.0.1"", ++ ""grant-express"": ""4.1.2"", + ""helmet"": ""3.8.2"",",Why this version of `grant-express`? And should we pin everything else too?,2018-11-21 10:11:41 +214,"@@ -411,6 +424,10 @@ class Uppy { + const removedFile = updatedFiles[fileID] + delete updatedFiles[fileID] + ++ this.removers.forEach((remover) => { ++ remover([fileID]) ++ })","Processor and uploader functions are kept in arrays in core because you can have multiple. I think a single remover function should be enough; it doesn't need a pipeline like uploads may need. + +Maybe this can be done by emitting a `remove-file` event here in `removeFile()`, and then listening for it in a `DeleteFiles` plugin instead?",2018-02-05 10:41:10 +153,"@@ -413,14 +424,7 @@ class Uppy { + * Set the preview URL for a file. + */ + setPreviewURL (fileID, preview) { +- const { files } = this.getState() +- this.setState({ +- files: Object.assign({}, files, { +- [fileID]: Object.assign({}, files[fileID], { +- preview: preview +- }) +- }) +- }) ++ this.setFileState(fileID, { preview: preview })",yay!,2017-12-09 16:05:26 +111,"@@ -414,4 +414,30 @@ describe('core/utils', () => { + ).toEqual('ws://foo.bar/a/b/cd?e=fghi&l=k&m=n') + }) + }) ++ ++ describe('settle', () => { ++ it('should reject if all input promises reject', () => { ++ return expect( ++ utils.settle([ ++ Promise.reject(new Error('oops')), ++ Promise.reject(new Error('this went wrong')) ++ ]) ++ ).rejects.toMatchObject({ ++ message: 'oops' ++ }) ++ }) ++ ++ it('should resolve with an object if some input promises resolve', () => { ++ return expect( ++ utils.settle([ ++ Promise.reject(new Error('rejected')), ++ Promise.resolve('resolved'), ++ Promise.resolve('also-resolved') ++ ]) ++ ).resolves.toMatchObject({",this promise support is a kinda neat thing about jest,2017-09-20 09:08:02 +125,"@@ -415,61 +422,93 @@ class Uppy { + }) + } + +- pauseResume (action, fileID) { ++ pauseResume (fileID) { ++ const updatedFiles = Object.assign({}, this.getState().files) ++ ++ if (updatedFiles[fileID].uploadComplete) return ++ ++ const wasPaused = updatedFiles[fileID].isPaused || false ++ const isPaused = !wasPaused ++ ++ let updatedFile ++ if (wasPaused) { ++ updatedFile = Object.assign({}, updatedFiles[fileID], { ++ isPaused: false ++ }) ++ } else { ++ updatedFile = Object.assign({}, updatedFiles[fileID], { ++ isPaused: true ++ }) ++ }","Not really related, but this `if` could be replaced with + +```js +const updatedFile = Object.assign({}, updatedFiles[fileID], { + isPaused: !wasPaused +}) +```",2017-10-03 11:06:31 +73,"@@ -415,7 +415,7 @@ class Uppy { + throttledCalculateProgress(data) + }) + +- this.on('core:upload-success', (fileID, uploadResp, uploadURL) => {","I think someone specifically asked for a full response object, and it makes sense. Is this removing uploadResp, or am I missing something?",2017-07-12 23:12:26 +85,"@@ -419,6 +437,20 @@ class Uppy { + this.addFile(data) + }) + ++ this.on('core:file-added', (file) => { ++ this.emit('core:generate-preview', file) ++ }) ++ ++ this.on('core:generate-preview', (file) => { ++ if (Utils.isPreviewSupported(file.type.specific) && !file.isRemote) { ++ Utils.createThumbnail(file, 200).then((thumbnail) => { ++ this.setPreviewURL(file.id, thumbnail) ++ }).catch((err) => { ++ console.warn(err.stack || err.message) ++ }) ++ } ++ })",Why event instead of method? Should we distinguish them more strictly?,2017-08-18 14:20:03 +944,"@@ -42,14 +54,38 @@ module.exports = class Provider extends RequestClient { + return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey) + } + +- authUrl () { +- return `${this.hostname}/${this.id}/connect` ++ authUrl (queries) {","Technically this is a breaking change. But the `authUrl()` function is not a public API, but one for use by provider-views. So I think we should do a major version bump to companion-client (because of this API change) and provider-views (because it expects the new API), but the provider modules themselves don't need one.",2020-11-16 12:51:13 +938,"@@ -42,14 +54,38 @@ module.exports = class Provider extends RequestClient { + return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey) + } + +- authUrl () { +- return `${this.hostname}/${this.id}/connect` ++ authUrl (queries) { ++ const urlQueries = [] ++ if (queries) { ++ urlQueries.push(queries) ++ } ++ ++ if (this.preAuthToken) { ++ urlQueries.push(`uppyPreAuthToken=${this.preAuthToken}`) ++ } ++ ++ queries = urlQueries.join('&')","Maybe we can reduce the room for error here by making `authUrl` take an object and using [`qs-stringify`](https://www.npmjs.com/package/qs-stringify)? The preAuthToken is not being URL-encoded here and that might be fine, but it's also something that's easy to forget when passing query strings into the `queries` argument.",2020-11-16 11:25:31 +779,"@@ -42,44 +37,150 @@ function progressIndicatorTitle (props) { + return '' + } + ++// function PauseResumeCancelIcon (props) {","I'd vote that, when we're ready to commit to master, it's time to remove large old functions as comments like this one and start relying on Git for history to retrieve them",2020-06-03 08:40:00 +924,"@@ -42,6 +44,20 @@ module.exports = class SharedHandler { + } else { + currentSelection = items.slice(currentIndex, prevIndex + 1) + } ++ // Check restrictions on each file in currentSelection, ++ // reduce it to only contain files that pass restrictions ++ currentSelection = currentSelection.reduce((reducedCurrentSelection, item) => { ++ const uppy = this.plugin.uppy ++ const validatedRestrictions = uppy.validateRestrictions( ++ remoteFileObjToLocal(item), ++ [...uppy.getFiles(), ...reducedCurrentSelection] ++ ) ++ if (!validatedRestrictions.result) { ++ uppy.info({ message: validatedRestrictions.reason }, 'error', 5000) ++ return reducedCurrentSelection ++ } ++ return [...reducedCurrentSelection, item] ++ })",@lakesare could you take a look at the reducer here? makes sense? thx!,2020-11-11 17:47:18 +503,"@@ -420,7 +420,7 @@ module.exports = class ProviderView { + handleAuth () { + const authState = btoa(JSON.stringify({ origin: getOrigin() })) + // @todo remove this hardcoded version +- const clientVersion = 'companion-client:1.0.2' ++ const clientVersion = encodeURIComponent('@uppy/companion-client=1.0.2')",`ProviderView` just got `VERSION` too.,2019-06-05 17:32:55 +402,"@@ -422,7 +422,7 @@ module.exports = class ProviderView { + } + + handleAuth () { +- const authState = btoa(JSON.stringify({ origin: location.origin })) ++ const authState = btoa(JSON.stringify({ origin: location.origin, redirect: 'http://localhost:3' })) + const link = `${this.provider.authUrl()}?state=${authState}`",`http://localhost:3` 🤔 ,2019-02-21 15:04:33 +534,"@@ -422,8 +422,7 @@ module.exports = class ProviderView { + + handleAuth () { + const authState = btoa(JSON.stringify({ origin: getOrigin() })) +- // @todo remove this hardcoded version +- const clientVersion = encodeURIComponent('@uppy/companion-client=1.0.2') ++ const clientVersion = encodeURIComponent(`@uppy/companion-client=${ProviderView.VERSION}`)",Hmm this should've been `@uppy/provider-views` I guess! Can we still change it now with back compat or will we just have to suck it up? :P ,2019-07-01 11:48:19 +582,"@@ -423,6 +423,27 @@ class Uppy { + } + } + ++ _showOrLogErrorAndThrow (err, showInformer = true) {","Maybe let's make it `(err, { showInformer = true } = {})`, so that we can use +``` +this._showOrLogErrorAndThrow('Cannot add the file'), { showInformer: true }) +``` +instead of less obvious +``` +this._showOrLogErrorAndThrow('Cannot add the file'), false) +``` +?",2019-08-23 22:32:32 +581,"@@ -423,6 +423,27 @@ class Uppy { + } + } + ++ _showOrLogErrorAndThrow (err, showInformer = true) { ++ const message = typeof err === 'object' ? err.message : err","Is `err` ever not an object? Looks like it's always an Error object in our code, and we don't need this check.",2019-08-23 22:28:19 +583,"@@ -423,6 +423,27 @@ class Uppy { + } + } + ++ _showOrLogErrorAndThrow (err, showInformer = true) { ++ const message = typeof err === 'object' ? err.message : err ++ const details = (typeof err === 'object' && err.details) ? err.details : ''",What's that `error.details` field? Do we define it somewhere?,2019-08-23 22:36:22 +908,"@@ -425,44 +426,54 @@ class Uppy { + } + + /** +- * Check if minNumberOfFiles restriction is reached before uploading. ++ * A public wrapper for _checkRestrictions — checks if file passes a set of restrictions. ++ * For use in UI pluigins (like Providers), to disallow selecting files that won’t pass restrictions. + * +- * @private ++ * @param {object} file object to check ++ * @returns {object} { result: true/false, reason: why file didn’t pass restrictions } + */ +- _checkMinNumberOfFiles (files) { +- const { minNumberOfFiles } = this.opts.restrictions +- if (Object.keys(files).length < minNumberOfFiles) { +- throw new RestrictionError(`${this.i18n('youHaveToAtLeastSelectX', { smart_count: minNumberOfFiles })}`) ++ passesRestrictions (file) { ++ console.log(file)",Forgotten `console.log`,2020-10-28 20:52:58 +930,"@@ -43,6 +44,7 @@ + ScreenCapture: document.querySelector('#opts-ScreenCapture'), + GoogleDrive: document.querySelector('#opts-GoogleDrive'), + Dropbox: document.querySelector('#opts-Dropbox'), ++ Box: document.querySelector('#opts-Box'),","excluding from examples in the meantime +```suggestion +```",2020-11-13 09:13:31 +946,"@@ -430,11 +447,23 @@ module.exports = class ProviderView { + } + } + +- listAllFiles (path, files = null) { ++ listAllFiles (path, files = null, meta = undefined) { + files = files || [] + return new Promise((resolve, reject) => { + this.provider.list(path).then((res) => {","This `res` is where we'd need `currentFolderName`. Currently, if `moreFiles === true`, this implementation won't reproduce the correct parent's folder names for **Google Drive** and **OneDrive** since their IDs are unique, hashed strings instead of folder names (IMHO, Dropbox took the cleverest approach here). + +FWIW, the `relativePath` in the `data` object is giving `/{fileId}`; and this is the reason that the above statement is relevant. + +Read more at https://github.com/transloadit/uppy/pull/2605#issuecomment-729799907.",2020-11-18 16:49:58 +945,"@@ -430,11 +447,23 @@ module.exports = class ProviderView { + } + } + +- listAllFiles (path, files = null) { ++ listAllFiles (path, files = null, meta = undefined) { + files = files || [] + return new Promise((resolve, reject) => { + this.provider.list(path).then((res) => { ++ let itemsRelativePath ++ ++ if (meta) {","My idea on having this condition here is that if there's a meta, then there's a `previousRelativePath` and a `currentFolder`. That's why I skipped checking those individual properties.",2020-11-18 16:41:33 +585,"@@ -434,15 +455,8 @@ class Uppy { + addFile (file) { + const { files, allowNewUpload } = this.getState() + +- const onError = (msg) => { +- const err = typeof msg === 'object' ? msg : new Error(msg) +- this.log(err.message) +- this.info(err.message, 'error', 5000) +- throw err +- } +- + if (allowNewUpload === false) { +- onError(new Error('Cannot add new files: already uploading.')) ++ this._showOrLogErrorAndThrow(new RestrictionError('Cannot add new files: already uploading.'))","Should we emit `this.emit('restriction-failed', null, err)` on every RestrictionError, like we do in `upload()`?",2019-08-23 23:22:29 +79,"@@ -44,45 +44,45 @@ module.exports = class Informer extends Plugin { + this.render = this.render.bind(this) + } + +- showInformer (msg, type, duration) { +- this.core.setState({ +- informer: { +- isHidden: false, +- type: type, +- msg: msg +- } +- }) ++ // showInformer (msg, type, duration) { ++ // this.core.setState({ ++ // informer: { ++ // isHidden: false, ++ // type: type, ++ // msg: msg ++ // } ++ // }) + +- window.clearTimeout(this.timeoutID) +- if (duration === 0) { +- this.timeoutID = undefined +- return +- } ++ // window.clearTimeout(this.timeoutID) ++ // if (duration === 0) { ++ // this.timeoutID = undefined ++ // return ++ // } + +- // hide the informer after `duration` milliseconds +- this.timeoutID = setTimeout(() => { +- const newInformer = Object.assign({}, this.core.getState().informer, { +- isHidden: true +- }) +- this.core.setState({ +- informer: newInformer +- }) +- }, duration) +- } ++ // // hide the informer after `duration` milliseconds ++ // this.timeoutID = setTimeout(() => { ++ // const newInformer = Object.assign({}, this.core.getState().informer, { ++ // isHidden: true ++ // }) ++ // this.core.setState({ ++ // informer: newInformer ++ // }) ++ // }, duration) ++ // } + +- hideInformer () { +- const newInformer = Object.assign({}, this.core.getState().informer, { +- isHidden: true +- }) +- this.core.setState({ +- informer: newInformer +- }) +- } ++ // hideInformer () { ++ // const newInformer = Object.assign({}, this.core.getState().informer, { ++ // isHidden: true ++ // }) ++ // this.core.setState({ ++ // informer: newInformer ++ // }) ++ // }",Could remove all the commented out stuff here :),2017-07-25 13:28:48 +676,"@@ -44,9 +44,12 @@ module.exports = class Client { + body: data + }).then((response) => response.json()).then((assembly) => { + if (assembly.error) { +- const error = new Error(assembly.error) ++ const error = new Error(assembly) + error.message = assembly.error","hmm, I think we can just do `new Error(assembly.error)` and that should set `error.message` correctly too. I don't know why it was done this way with a separate `.message` assignment before :sweat_smile: + +Should we do `error.assembly = assembly` so the template editor can access it that way, rather than parsing `error.details`?",2020-02-10 10:20:37 +666,"@@ -44,9 +44,9 @@ module.exports = class Client { + body: data + }).then((response) => response.json()).then((assembly) => { + if (assembly.error) { +- const error = new Error(assembly.error) ++ const error = new Error(assembly) + error.message = assembly.error +- error.details = assembly.reason ++ error.details = `${assembly.message} Assembly ID: ${assembly.assembly_id}`","@Acconut Marius, I added `assembly_id`, not sure how to best include all of the error response in Uppy’s error message, as you proposed in https://github.com/transloadit/uppy/issues/2000. Maybe you’ve got suggestions? :)",2020-01-07 16:50:01 +238,"@@ -446,20 +446,15 @@ class Uppy { + } + + pauseResume (fileID) { +- const updatedFiles = Object.assign({}, this.getState().files) +- +- if (updatedFiles[fileID].uploadComplete) return ++ if (this.getFile(fileID).uploadComplete) return + +- const wasPaused = updatedFiles[fileID].isPaused || false ++ const wasPaused = this.getFile(fileID).isPaused || false + const isPaused = !wasPaused + +- const updatedFile = Object.assign({}, updatedFiles[fileID], { ++ this.setFileState(fileID, { + isPaused: isPaused + }) + +- updatedFiles[fileID] = updatedFile +- this.setState({files: updatedFiles}) +- + this.emit('upload-pause', fileID, isPaused)",:clap: ,2018-03-12 12:01:45 +356,"@@ -446,6 +446,10 @@ this.info({ + + Subscribe to an uppy-event. See below for the full list of events. + ++### `uppy.off('event', action)` ++ ++Unsubscribe to an uppy-event. See below for the full list of events. ++",Minor neat-pick: “unsubscribe from?”,2018-09-26 21:09:27 +579,"@@ -448,11 +448,18 @@ module.exports = class Tus extends Plugin { + + handleUpload (fileIDs) { + if (fileIDs.length === 0) { +- this.uppy.log('Tus: no files to upload!') ++ this.uppy.log('[Tus] No files to upload') + return Promise.resolve() + } + +- this.uppy.log('Tus is uploading...') ++ if (fileIDs.length > 10 && this.opts.limit === 0) {",Shall we always throw this warning if a limit wasnt set?,2019-08-21 16:49:55 +846,"@@ -448,6 +463,36 @@ The class must also have an `authProvider` string (lowercased) field which typic + } + ``` + ++## Migrating v1 to v2 ++ ++### Prerequisite ++ ++Since v2, you now need to be running `node.js > v10.0.0` to use Companion.",Should this be `>= v10.0.0`?,2020-07-16 06:54:55 +878,"@@ -448,6 +463,36 @@ The class must also have an `authProvider` string (lowercased) field which typic + } + ``` + ++## Migrating v1 to v2 ++ ++### Prerequisite ++ ++Since v2, you now need to be running `node.js >= v10.0.0` to use Companion.","```suggestion +Since v2, you now need to be running `node.js >= v10.20.1` to use Companion. +```",2020-09-07 09:38:25 +289,"@@ -448,7 +448,7 @@ class Uppy { + this.scheduledAutoProceed = setTimeout(() => { + this.scheduledAutoProceed = null + this.upload().catch((err) => { +- console.error(err.stack || err.message || err) ++ onError(err.stack || err.message || err)","`upload()` already logs an error and shows the informer, so we don't need to use `onError` here. (`console.error` is probably not that necessary either)",2018-05-31 10:21:00 +759,"@@ -449,7 +449,6 @@ class Uploader { + uploadUrl: this.options.uploadUrl, + // @ts-ignore + uploadLengthDeferred: false, +- resume: true,",The `resume` option did not have any effect when used inside Node.js without specifying the `urlStorage` parameter as well. So this can be removed.,2020-05-03 15:45:45 +90,"@@ -45,3 +45,356 @@ + line-height: 40px; + } + } ++ ++.UppyInformer span { ++ line-height: 12px; ++ width: 13px; ++ height: 13px; ++ display: inline-block; ++ vertical-align: middle; ++ background-color: $color-white; ++ border-radius: 50%; ++ position: relative; ++ top: -1px; ++ left: 5px; ++ font-size: 10px; ++ margin-left: -1px; ++} ++ ++.UppyInformer span:after { ++ line-height: 1.3; ++ word-wrap: break-word; ++} ++ ++// balloon ++// https://kazzkiq.github.io/balloon.css/","Minor, but perhaps this could be in a separate file?",2017-08-28 08:01:25 +297,"@@ -455,7 +455,7 @@ module.exports = class ProviderView { + const handleToken = (e) => { + const allowedOrigin = new RegExp(noProtocol(this.plugin.opts.hostPattern)) + if (!allowedOrigin.test(noProtocol(e.origin)) || e.source !== authWindow) { +- console.log(`rejecting event from ${e.origin} vs allowed pattern ${this.plugin.opts.hostPattern}`) ++ this.plugin.uppy.log(`rejecting event from ${e.origin} vs allowed pattern ${this.plugin.opts.hostPattern}`)",:+1: ,2018-06-11 09:09:05 +671,"@@ -455,8 +457,9 @@ class Uploader { + } + } + ) ++ const httpMethod = (this.options.httpMethod || '').toLowerCase() === 'put' ? 'put' : 'post'",nice :+1: ,2020-02-03 10:09:34 +135,"@@ -457,6 +451,15 @@ module.exports = class Transloadit extends Plugin { + onAssemblyError(assembly, error) + } + ++ const checkAllComplete = () => {","Moved this check from `onAssemblyFinished` into here, so we don't reject the entire upload anymore if an assembly fails. Instead, the files belonging to that assembly are added to the `{ failed }` result array.",2017-11-10 16:14:57 +366,"@@ -458,7 +459,12 @@ module.exports = class Dashboard extends Plugin { + this.uppy.on('plugin-remove', this.removeTarget) + this.uppy.on('file-added', (ev) => { + this.toggleAddFilesPanel(false) +- this.hideAllPanels() ++ }) ++ this.uppy.on('complete', ({ failed, uploadID }) => { ++ if (this.opts.closeAfterFinish && failed.length === 0) { ++ // All uploads are done ++ this.requestCloseModal() ++ }",Should this event listener be removed `.off` in `uninstall` too?,2018-10-15 15:49:40 +475,"@@ -458,8 +458,8 @@ module.exports = class ProviderView { + + const patterns = Array.isArray(allowedOrigin) ? allowedOrigin.map(getRegex) : [getRegex(allowedOrigin)] + return patterns +- .filter((pattern) => pattern !== null) +- .some((pattern) => pattern.test(origin)) ++ .filter((pattern) => pattern != null) // loose comparison to catch undefined","I wonder if it’s better to explicitly check for `undefined` for readability. But with your comment this works, just thinking out loud.",2019-05-23 12:23:36 +10,"@@ -46,12 +40,18 @@ export default class Tus10 extends Plugin { + percentage = Math.round(percentage) + + // Dispatch progress event +- this.core.emitter.emit('progress', { +- plugin: this, +- percentage: percentage ++ this.core.emitter.emit('upload-progress', {","We could potentially destructure `emitter` and `log` from `this.core` if we have to call them a bunch, but it may be better to be explicit about using `this.core.emitter`, etc. + +For instance: + +`const { emitter, log } = this.core` +",2016-04-04 15:53:58 +128,"@@ -46,14 +46,44 @@ module.exports = { + Dropbox, + Instagram, + FileInput, +- Tus10, ++ Tus, + XHRUpload, + Transloadit, + AwsS3, + Dashboard, + MetaData, + Webcam, +- RestoreFiles, ++ GoldenRetriever, + ReduxDevTools, + ReduxStore + } ++ ++Object.defineProperty(module.exports, 'RestoreFiles', { ++ enumerable: true, ++ configurable: true, ++ get: () => { ++ console.warn('Uppy.RestoreFiles is deprecated and will be removed in v0.22. Use Uppy.GoldenRetriever instead.') ++ Object.defineProperty(module.exports, 'RestoreFiles', { ++ enumerable: true, ++ configurable: true, ++ writable: true, ++ value: GoldenRetriever ++ }) ++ return GoldenRetriever ++ } ++}) ++ ++Object.defineProperty(module.exports, 'Tus10', { ++ enumerable: true, ++ configurable: true, ++ get: () => { ++ console.warn('Uppy.Tus10 is deprecated and will be removed in v0.22. Use Uppy.Tus instead.') ++ Object.defineProperty(module.exports, 'Tus10', { ++ enumerable: true, ++ configurable: true, ++ writable: true, ++ value: Tus ++ }) ++ return Tus ++ } ++})",Wow! 😎 ,2017-10-17 16:16:51 +787,"@@ -46,19 +50,28 @@ class AddFiles extends Component { + ) + } + +- renderHiddenFileInput = () => { ++ renderCloudIcon = () => { ++ return ( ++ ++ ++ ++ ) ++ } ++ ++ renderHiddenInput = (isFolder, refName) => { + return ( + { this.fileInput = ref }} ++ ref={(ref) => { this[refName] = ref }}","I wonder if this entire `ref` function should be passed in as a parameter to `renderHiddenInput`, just like the `onClickFn` in `renderBrowseButton()`? I'm a bit uneasy about using `this[someDynamicValue]`, even though it's technically not wrong :) + +(this is not a blocker, feel free to ignore this suggestion if you disagree)",2020-06-24 11:30:36 +57,"@@ -46,6 +46,36 @@ function getUploadingState (props, files) { + return state + } + ++function calculateProcessingProgress (files) { ++ // Collect pre or postprocessing progress states. ++ const progresses = [] ++ Object.keys(files).forEach((fileID) => { ++ const { progress } = files[fileID] ++ if (progress.preprocess) { ++ progresses.push(progress.preprocess) ++ } ++ if (progress.postprocess) { ++ progresses.push(progress.postprocess) ++ } ++ }) ++ ++ // In the future we should probably do this differently. For now we'll take the ++ // mode and message from the first file… ++ const { mode, message } = progresses[0] ++ const value = progresses.filter(isDeterminate).reduce((total, progress, index, all) => { ++ return total + progress.value / all.length ++ }, 0) ++ function isDeterminate (progress) { ++ return progress.mode === 'determinate' ++ } ++ ++ return { ++ mode, ++ message, ++ value ++ }","This function was moved here from `ProgressBarProcessing`, no changes otherwise.",2017-06-23 13:15:36 +331,"@@ -46,7 +46,7 @@ spec: + - companion + topologyKey: kubernetes.io/hostname + containers: +- - image: docker.io/transloadit/companion:latest ++ - image: docker.io/kiloreux/uppy-companion:latest",Should be transloadit,2018-08-17 05:11:41 +184,"@@ -46,7 +46,8 @@ module.exports = class StatusBar extends Plugin { + target: 'body', + hideUploadButton: false, + showProgressDetails: false, +- locale: defaultLocale ++ locale: defaultLocale, ++ hideAfterFinish: false",Would it make sense to default this to `true`?,2018-01-01 22:40:36 +124,"@@ -46,8 +46,17 @@ function getFiles (store) { + }) + } + ++function probe (event) { ++ sendMessageToAllClients({ ++ type: 'uppy/HERE_I_AM' ++ }) ++}","MDN said something about using `clients.get(event.clientId)` to only send the message back to the sender, but `clientId` was undefined for me--i guess that's why we were sending the `uppy/ALL_FILES` message to all clients too.",2017-10-02 09:44:31 +771,"@@ -464,6 +466,7 @@ module.exports = class Tus extends Plugin { + this.uppy.emit('upload-success', file, uploadResp) + this.resetUploaderReferences(file.id) + queuedRequest.done()","I think these should also be flipped. This is when a 'remote' upload has finished, eg. when you select files from Google Drive.",2020-05-13 11:11:58 +474,"@@ -47,15 +46,18 @@ class Uploader { + + this.options = options + this.token = uuid.v4() +- this.options.path = `${this.options.pathPrefix}/${Uploader.FILE_NAME_PREFIX}-${this.token}` ++ this.path = `${this.options.pathPrefix}/${Uploader.FILE_NAME_PREFIX}-${this.token}` ++ this.metadata = Object.assign({}, this.options.metadata || {}) ++ this.metadata.filename = this.metadata.name || path.basename(this.path) ++ this.metadata.filetype = this.metadata.type + this.streamsEnded = false","What about adding this `filename` and `filetype` conversion to `uploadRemote` on `@uppy/tus` client instead? Then it’s consistent — tusd expects metadata this way, it doesn’t convert `name` to `filename` for you, and so will Companion. We have that conversion for direct uploads, and we’ll do the same in the same place for remote uploads. + +https://github.com/transloadit/uppy/blob/master/packages/%40uppy/tus/src/index.js#L180-L184",2019-05-23 07:40:38 +3,"@@ -47,6 +47,7 @@ + ""zuul"": ""^3.7.2"" + }, + ""dependencies"": { +- ""async"": ""^1.5.0"" ++ ""async"": ""^1.5.0"",","This can be removed I think then? +",2015-12-07 14:12:01 +900,"@@ -47,7 +47,7 @@ class Zoom extends Provider { + } + + if (!from && !to && !meetingId) { +- const end = cursor && moment.utc(cursor).endOf('day').tz(userResponse.timezone || 'UTC') ++ const end = cursor && moment.utc(cursor).endOf('day').tz(userBody.timezone || 'UTC')","caught a bug while testing. `userResponse` is a response object, not body",2020-10-19 07:41:49 +953,"@@ -47,7 +48,8 @@ module.exports.addToCookies = (res, token, companionOptions, providerName) => { + /** + * + * @param {object} res +- * @param {object=} companionOptions ++ * @param {object} companionOptions ++ * @param {string=} companionOptions.cookieDomain","```suggestion +```",2020-11-23 07:26:56 +868,"@@ -471,54 +472,59 @@ class Uploader { + const headers = headerSanitize(this.options.headers) + const reqOptions = { url: this.options.endpoint, headers, encoding: null } + if (this.options.useFormData) { +- reqOptions.formData = Object.assign( +- {}, +- this.options.metadata, +- { +- [this.options.fieldname]: { +- value: file, +- options: { +- filename: this.uploadFileName, +- contentType: this.options.metadata.type +- } +- } ++ const form = new FormData() ++ for (const property in this.options.metadata) { ++ form.append(property, this.options.metadata[property]) ++ } ++ form.append('file', file)","the original code adds a filename and fieldname if they exist so I think we should be doing something like this: + +```suggestion + form.append(this.options.fieldname, file, { + filename: this.uploadFileName, + contentType: this.options.metadata.type + }) +```",2020-08-21 11:32:30 +870,"@@ -471,54 +472,59 @@ class Uploader { + const headers = headerSanitize(this.options.headers) + const reqOptions = { url: this.options.endpoint, headers, encoding: null } + if (this.options.useFormData) { +- reqOptions.formData = Object.assign( +- {}, +- this.options.metadata, +- { +- [this.options.fieldname]: { +- value: file, +- options: { +- filename: this.uploadFileName, +- contentType: this.options.metadata.type +- } +- } ++ const form = new FormData() ++ for (const property in this.options.metadata) { ++ form.append(property, this.options.metadata[property]) ++ } ++ form.append('file', file) ++ form.getLength((error, length) => { ++ if (error) { ++ logger.error(error, 'upload.multipart.error')","```suggestion + logger.error(error, 'upload.multipart.size.error') + this.emitError(error) + return +```",2020-08-21 12:48:27 +869,"@@ -471,54 +472,59 @@ class Uploader { + const headers = headerSanitize(this.options.headers) + const reqOptions = { url: this.options.endpoint, headers, encoding: null } + if (this.options.useFormData) { +- reqOptions.formData = Object.assign( +- {}, +- this.options.metadata, +- { +- [this.options.fieldname]: { +- value: file, +- options: { +- filename: this.uploadFileName, +- contentType: this.options.metadata.type +- } +- } ++ const form = new FormData() ++ for (const property in this.options.metadata) { ++ form.append(property, this.options.metadata[property]) ++ } ++ form.append('file', file) ++ form.getLength((error, length) => { ++ if (error) { ++ logger.error(error, 'upload.multipart.error') + } +- ) ++ reqOptions.headers['content-length'] = length ++ const req = request[httpMethod](reqOptions, (error, response, body) => this._handleUploadMultipart(error, response, body, bytesUploaded)) ++ // @ts-ignore ++ req._form = form ++ }) + } else { ++ const stats = fs.statSync(this.path) ++ const fileSizeInBytes = stats.size ++ reqOptions.headers['content-length'] = fileSizeInBytes","based on [this comment](https://github.com/transloadit/uppy/pull/2387#issuecomment-678238507), I don't think we need to do anything for the case where `this.options.useFormData` is `false`",2020-08-21 12:17:44 +871,"@@ -471,54 +472,59 @@ class Uploader { + const headers = headerSanitize(this.options.headers) + const reqOptions = { url: this.options.endpoint, headers, encoding: null } + if (this.options.useFormData) { +- reqOptions.formData = Object.assign( +- {}, +- this.options.metadata, +- { +- [this.options.fieldname]: { +- value: file, +- options: { +- filename: this.uploadFileName, +- contentType: this.options.metadata.type +- } +- } ++ const form = new FormData() ++ for (const property in this.options.metadata) { ++ form.append(property, this.options.metadata[property]) ++ } ++ form.append('file', file) ++ form.getLength((error, length) => { ++ if (error) { ++ logger.error(error, 'upload.multipart.error') + } +- ) ++ reqOptions.headers['content-length'] = length ++ const req = request[httpMethod](reqOptions, (error, response, body) => this._handleUploadMultipart(error, response, body, bytesUploaded)) ++ // @ts-ignore ++ req._form = form ++ }) + } else { ++ const stats = fs.statSync(this.path) ++ const fileSizeInBytes = stats.size ++ reqOptions.headers['content-length'] = fileSizeInBytes + reqOptions.body = file ++ request[httpMethod](reqOptions, (error, response, body) => this._handleUploadMultipart(error, response, body, bytesUploaded)) + } ++ } + +- request[httpMethod](reqOptions, (error, response, body) => { +- if (error) { +- logger.error(error, 'upload.multipart.error') +- this.emitError(error) +- return +- } +- const headers = response.headers +- // remove browser forbidden headers +- delete headers['set-cookie'] +- delete headers['set-cookie2'] +- +- const respObj = { +- responseText: body.toString(), +- status: response.statusCode, +- statusText: response.statusMessage, +- headers +- } ++ _handleUploadMultipart (error, response, body, bytesUploaded) {",should we rename this to `_onMultipartComplete` or something similar?,2020-08-21 12:55:04 +872,"@@ -471,54 +472,64 @@ class Uploader { + const headers = headerSanitize(this.options.headers) + const reqOptions = { url: this.options.endpoint, headers, encoding: null } + if (this.options.useFormData) { +- reqOptions.formData = Object.assign( +- {}, +- this.options.metadata, +- { +- [this.options.fieldname]: { +- value: file, +- options: { +- filename: this.uploadFileName, +- contentType: this.options.metadata.type +- } +- } ++ const form = new FormData() ++ for (const property in this.options.metadata) { ++ form.append(property, this.options.metadata[property]) ++ } ++ form.append(this.options.fieldname, file, { ++ filename: this.uploadFileName, ++ contentType: this.options.metadata.type ++ }) ++ form.getLength((error, length) => { ++ if (error) { ++ logger.error(error, 'upload.multipart.size.error') ++ this.emitError(error) ++ return + } +- ) ++ reqOptions.headers['content-length'] = length ++ const req = request[httpMethod](reqOptions, (error, response, body) => this._onMultipartComplete(error, response, body, bytesUploaded)) ++ // @ts-ignore ++ req._form = form ++ }) + } else { ++ const stats = fs.statSync(this.path) ++ const fileSizeInBytes = stats.size ++ reqOptions.headers['content-length'] = fileSizeInBytes + reqOptions.body = file ++ request[httpMethod](reqOptions, (error, response, body) => this._onMultipartComplete(error, response, body, bytesUploaded))","```suggestion + fs.stat(this.path, (err, stats) => { + if (err) { + logger.error(err, 'upload.multipart.size.error') + this.emitError(err) + return + } + + const fileSizeInBytes = stats.size + reqOptions.headers['content-length'] = fileSizeInBytes + reqOptions.body = file + request[httpMethod](reqOptions, (error, response, body) => this._onMultipartComplete(error, response, body, bytesUploaded)) + }) +```",2020-08-28 11:18:59 +923,"@@ -471,6 +478,9 @@ class Uploader { + const headers = headerSanitize(this.options.headers) + const reqOptions = { url: this.options.endpoint, headers, encoding: null } + const httpRequest = request[httpMethod] ++ if (this.options.insecureUpload) {",what is this option for? 🤔 ,2020-11-11 13:27:37 +569,"@@ -472,6 +472,13 @@ class Uppy { + + const fileID = generateFileID(file) + ++ if (files[fileID]) { ++ this.info(`Not adding duplicate file '${fileName}', it already exists`, 'error', 5000) ++ this.log(`Not adding duplicate file '${fileName}', it already exists`)","Is this causing multiple log statements? If so, is it intended?",2019-08-12 15:24:47 +906,"@@ -473,6 +474,21 @@ class Uppy { + } + } + ++ // We can't check maxTotalFileSize if the size is unknown. ++ if (maxTotalFileSize && file.data.size != null) { ++ let totalFilesSize = 0 ++ totalFilesSize += file.size",Should we use `file.data.size` here too?,2020-10-23 10:34:06 +998,"@@ -476,7 +476,11 @@ module.exports = class Webcam extends Plugin { + } + + getVideo () { +- const mimeType = this.recordingChunks[0].type ++ // Sometimes in iOS Safari, Blobs (especially the first Blob in the recordingChunks Array) ++ // have empty 'type' attributes (e.g. '') so we need to find a Blob that has a defined 'type' ++ // attribute in order to determine the correct MIME type. ++ const mimeType = this.recordingChunks.find(blob => blob.type?.length > 0).type",is it safe for us to use the `blob.type?.length` optional chaining with IE11 support? @goto-bus-stop ,2021-04-08 20:11:24 +133,"@@ -477,7 +477,7 @@ class Uppy { + retryAll () { + const updatedFiles = Object.assign({}, this.getState().files) + const filesToRetry = Object.keys(updatedFiles).filter(file => { +- return updatedFiles[file].error ++ return updatedFiles[file].error.message","Should we be checking if `error.message` exists first? What if string is returned from somewhere? Though I think we have an Eslint rule for that now, an extra check would not be too bad?",2017-11-02 03:08:09 +633,"@@ -48,6 +48,10 @@ matrix: + env: COMPANION=true + addons: + apt: *APT ++ - node_js: 6 ++ env: COMPANION_NODE6=true","We can just reuse the `COMPANION=true` env var again here, I think, similarly to how we have 2 jobs for `UNIT=true` (one on stable node and one on node 10)",2019-11-23 12:13:38 +852,"@@ -480,6 +483,16 @@ class Uppy { + })) + } + } ++ ++ // We can't check minFileSize if the size is unknown. ++ if (minFileSize && file.data.size != null) { ++ if (file.data.size < minFileSize) { ++ throw new RestrictionError(this.i18n('inferiorSize2', { ++ backwardsCompat: this.i18n('inferiorSize'), ++ size: prettierBytes(minFileSize) ++ }))","```suggestion + throw new RestrictionError(this.i18n('inferiorSize', { + size: prettierBytes(minFileSize) + })) +```",2020-07-27 10:56:57 +492,"@@ -480,7 +480,8 @@ class Uploader { + if (error) { + this.emitError(error) + } else { +- this.emitSuccess(null, { ++ const url = data && data.Location ? data.Location : null;","```suggestion + const url = data && data.Location ? data.Location : null +```",2019-05-30 08:18:35 +129,"@@ -486,16 +483,36 @@ class Uppy { + }) + updatedFiles[file] = updatedFile + }) +- this.setState({files: updatedFiles}) ++ this.setState({ ++ files: updatedFiles, ++ error: null ++ }) + + this.emit('core:retry-all', filesToRetry) ++ ++ const uploadID = this.createUpload(filesToRetry) ++ return this.runUpload(uploadID) ++ } ++ ++ retryUpload (fileID) { ++ const updatedFiles = Object.assign({}, this.state.files) ++ const updatedFile = Object.assign({}, updatedFiles[fileID], ++ { error: null, isPaused: false } ++ ) ++ updatedFiles[fileID] = updatedFile ++ this.setState({ ++ files: updatedFiles ++ }) ++ ++ this.emit('core:upload-retry', fileID) ++ ++ const uploadID = this.createUpload([ fileID ]) ++ return this.runUpload(uploadID) + } + + reset () { + this.cancelAll() + // this.pauseAll()",we might as well delete this one too 😄 ,2017-10-17 19:06:33 +164,"@@ -486,6 +707,9 @@ module.exports = class Transloadit extends Plugin { + this.uppy.on('upload-success', this.onFileUploadURLAvailable) + } + ++ this.uppy.on('restore:get-data', this.getPersistentData) ++ this.uppy.on('restored', this.onRestored) ++",So will `restore:` here a goldenretriever-specific event and `restored` a global one?,2017-12-12 03:28:14 +720,"@@ -49,24 +49,35 @@ class FileCard extends Component { + + renderMetaFields = () => { + const metaFields = this.props.metaFields || [] ++ const fieldCSSClasses = { ++ text: 'uppy-u-reset uppy-c-textInput uppy-Dashboard-FileCard-input' ++ } + + return metaFields.map((field) => { + const id = `uppy-Dashboard-FileCard-input-${field.id}` + return ( +
    + +- this.tempStoreMeta(ev, field.id)} +- data-uppy-super-focusable +- /> ++ {field.render !== undefined ++ ? field.render({ ++ value: this.state.formState[field.id], ++ onChange: (newVal) => this.updateMeta(newVal, field.id), ++ fieldCSSClasses: fieldCSSClasses ++ }, h) ++ : ( ++ { +- return !updatedFiles[file].progress.uploadComplete && +- updatedFiles[file].progress.uploadStarted +- }) +- +- switch (action) { +- case 'toggle': +- if (updatedFiles[fileID].uploadComplete) return +- +- const wasPaused = updatedFiles[fileID].isPaused || false +- const isPaused = !wasPaused +- let updatedFile +- if (wasPaused) { +- updatedFile = Object.assign({}, updatedFiles[fileID], { +- isPaused: false +- }) +- } else { +- updatedFile = Object.assign({}, updatedFiles[fileID], { +- isPaused: true +- }) +- } +- updatedFiles[fileID] = updatedFile +- this.core.setState({files: updatedFiles}) +- return isPaused +- case 'pauseAll': +- inProgressUpdatedFiles.forEach((file) => { +- const updatedFile = Object.assign({}, updatedFiles[file], { +- isPaused: true +- }) +- updatedFiles[file] = updatedFile +- }) +- this.core.setState({files: updatedFiles}) +- return +- case 'resumeAll': +- inProgressUpdatedFiles.forEach((file) => { +- const updatedFile = Object.assign({}, updatedFiles[file], { +- isPaused: false +- }) +- updatedFiles[file] = updatedFile +- }) +- this.core.setState({files: updatedFiles}) +- } +- } +- + handlePauseAll () { +- this.pauseResume('pauseAll') ++ this.core.pauseResume('pauseAll') + } + + handleResumeAll () { +- this.pauseResume('resumeAll') ++ this.core.pauseResume('resumeAll') ++ } ++ ++ handleRetryAll () { ++ this.core.pauseResume('retryAll') + }",I guess these pause-all/resume-all/retry-all event handlers could also be moved to core,2017-10-02 09:05:48 +257,"@@ -49,7 +49,8 @@ class Tabs extends Component { + tabindex=""-1"" + type=""file"" + name=""files[]"" +- multiple=""true"" ++ multiple={this.props.maxNumberOfFiles !== 1 || !this.props.maxNumberOfFiles}",same here,2018-05-09 15:51:47 +709,"@@ -492,18 +502,25 @@ class Uploader { + }) + } + +- /** +- * Upload the file to S3 while it is still being downloaded. +- */ +- uploadS3Multipart () { ++ beginTailReadStream () { + const file = createTailReadStream(this.path, {",we are dropping the use of tail read stream as seen [here](https://github.com/transloadit/uppy/pull/2114). So maybe we should as well do without in this PR?,2020-03-11 18:17:36 +156,"@@ -492,7 +492,7 @@ function _emitSocketProgress (uploader, progressData, file) { + const {progress, bytesUploaded, bytesTotal} = progressData + if (progress) { + uploader.core.log(`Upload progress: ${progress}`)",I think these `uploader.core` references also need to be changed to `.uppy`,2017-12-09 16:09:47 +592,"@@ -496,6 +494,25 @@ module.exports = class ProviderView { + } + } + ++ listAllFiles (path, files = null) { ++ files = files || [] ++ return new Promise((resolve) => { ++ this.provider.list(path).then((res) => {",should we add a `catch` for this call. Otherwise what will happen when the call to `this.provider.list` fails?,2019-08-29 19:09:35 +593,"@@ -496,6 +494,25 @@ module.exports = class ProviderView { + } + } + ++ listAllFiles (path, files = null) { ++ files = files || [] ++ return new Promise((resolve) => { ++ this.provider.list(path).then((res) => { ++ res.items.forEach((item) => { ++ if (!item.isFolder) { ++ files.push(item) ++ } ++ }) ++ let moreFiles = res.nextPagePath || null ++ if (moreFiles) { ++ return this.listAllFiles(moreFiles, files).then((files) => resolve(files))",do we need to add a `catch` here too? 🤔 ,2019-08-29 19:39:24 +271,"@@ -498,7 +498,7 @@ module.exports = class ProviderView { + } + + // split url because chrome adds '#' to redirects +- if (authWindowUrl && authWindowUrl.split('#')[0] === redirect) { ++ if (authWindowUrl && (authWindowUrl === redirect || authWindowUrl.split('#')[0] === redirect)) {","Hi, what scenario does this solve? Testing in chrome, the current implementation already covers for both scenarios. + +```js +""yahoo.com?redherring=3894"".split('#') +[""yahoo.com?redherring=3894""] +""yahoo.com?redherring=3894#"".split('#') +(2) [""yahoo.com?redherring=3894"", """"] +``` + +Or does `.split` behave differently in other browsers? +",2018-05-15 15:17:59 +456,"@@ -5,10 +5,10 @@ about: Do you need assistance with building the Uppy client in your bundler, or + labels: Not Accepted + --- + +-Transloadit is providing Uppy free of charge. If you want you can self-host all components and never pay us a dime. There's docs and tests and your Bug Reports and Feature Requests are always welcome on GitHub. ++Transloadit is providing Uppy free of charge. If you want, you can self-host all of its components and never pay us a dime. There are docs and tests, and your bug reports and feature requests are always welcome on GitHub. + +-There is also a different category of support that we'd like to call Integration Help: making things work for you, that are already reported working for the larger community. ++There is also a different category of support that we like to call Integration Help. It means that you will be taking advantage of all the knowledge already available within the Uppy community, to help you with all kinds of things that have already been reported as working.","For the three support categories: Bug Reports, Feature Requests, Integration Help, you keep uppercasing for the latter but ditch for the former 2 @AJvanLoon ?",2019-04-25 17:27:21 +644,"@@ -5,11 +5,17 @@ + * @returns {object} {name, extension} + */ + module.exports = function getFileNameAndExtension (fullFileName) { +- var re = /(?:\.([^.]+))?$/ +- var fileExt = re.exec(fullFileName)[1] +- var fileName = fullFileName.replace('.' + fileExt, '') +- return { +- name: fileName, +- extension: fileExt ++ const lastDot = fullFileName.lastIndexOf('.') ++ // these count as no extension: ""no-dot"", ""trailing-dot."" ++ if (lastDot === -1 || lastDot === fullFileName.length - 1) { ++ return { ++ name: fullFileName, ++ extension: undefined","``` +declare module '@uppy/utils/lib/getFileNameAndExtension' { + function getFileNameAndExtension(filename: string): { name: string, extension: string }; + export = getFileNameAndExtension +} +``` + +Let's make the extension optional in types too?",2019-12-01 16:00:59 +916,"@@ -5,15 +5,43 @@ const FooterActions = require('./FooterActions') + const { h } = require('preact') + + const Browser = (props) => { +- let filteredFolders = props.folders +- let filteredFiles = props.files ++ const { ++ currentSelection, ++ folders, ++ files, ++ uppyFiles, ++ filterItems, ++ filterInput, ++ maxNumberOfFiles, ++ maxTotalFileSize ++ } = props + +- if (props.filterInput !== '') { +- filteredFolders = props.filterItems(props.folders) +- filteredFiles = props.filterItems(props.files) ++ let filteredFolders = folders ++ let filteredFiles = files ++ ++ if (filterInput !== '') { ++ filteredFolders = filterItems(folders) ++ filteredFiles = filterItems(files) ++ } ++ ++ const selected = currentSelection.length ++ let canSelectMore = true ++ ++ if (maxNumberOfFiles && (uppyFiles.length + selected >= maxNumberOfFiles)) { ++ canSelectMore = false + } + +- const selected = props.currentSelection.length ++ let totalCurrentSelectionFileSize = 0 ++ ++ if (currentSelection) { ++ currentSelection.forEach(file => { ++ totalCurrentSelectionFileSize += file.size ++ }) ++ } ++ ++ if (maxTotalFileSize && totalCurrentSelectionFileSize >= maxTotalFileSize) {",Should this be `uppyFilesSizes + totalCurrentSelectionFileSize >= maxTotalFileSize`?,2020-11-10 08:27:50 +102,"@@ -5,16 +5,18 @@ const sampleImageDataURI = + + describe('core/utils', () => { + describe('generateFileID', () => { +- it('should take the filename object and produce a lowercase file id made up of the name and lastModified date', () => { ++ it('should take the filename object and produce a lowercase file id made up of uppy- prefix, file name (cleaned up to be lowercase, letters and numbers only), type, size and lastModified date', () => { + const fileObj = { + name: 'fOo0Fi@£$.jpg', ++ type: 'image/jpeg', + data: { +- lastModified: '2017-08-31T00:00:00.000Z' ++ lastModified: '2017-08-31T00:00:00.000Z',","Tangential nit, `lastModified` is a number in browsers. Doesn't have to be addressed in this PR but might be best for the test to mimic browser as closely as possible.",2017-09-11 07:49:19 +342,"@@ -5,7 +5,7 @@ + + + +-The AwsS3 plugin can be used to upload files directly to an S3 bucket. Uploads can be signed using Uppy Server or a custom signing function. ++The AwsS3 plugin can be used to upload files directly to an S3 bucket. Uploads can be signed using Companion or a custom signing function.","Elsewhere in documentation I've used ""Uppy Companion"". Would be best to pick one and use it consistently",2018-09-03 11:55:03 +576,"@@ -5,7 +5,7 @@ + + ++ + ```","It was kinda nice that it could point to the latest version automatically, can we achieve that with edgly?",2018-01-25 18:12:58 +814,"@@ -64,6 +64,7 @@ class Uppy { + connectedToInternet: 'Connected to the Internet', + // Strings for remote providers + noFilesFound: 'You have no files or folders here', ++ loadMore: 'Load more',",do we still need this? 🤔 ,2020-07-09 17:26:13 +838,"@@ -64,7 +64,11 @@ uppy.use(Webcam, { + 'picture' + ], + mirror: true, +- facingMode: 'user', ++ videoConstraints: { ++ facingMode: 'user', ++ width: { min: 720, ideal: 1280, max: 1920 }, ++ width: { min: 480, ideal: 800, max: 1080 },","via @arturi +```suggestion + height: { min: 480, ideal: 800, max: 1080 }, +```",2020-07-13 15:29:06 +385,"@@ -64,8 +64,7 @@ + transition: background-color, width .3s ease-out; + + &.is-indeterminate { +- background-color: $color-orange; +- $stripe-color: darken($color-orange, 10%);","Soo, no orange stripes for encoding then? 🤔",2018-12-06 11:22:24 +237,"@@ -643,13 +638,13 @@ class Uppy { + return + } + this.setFileState(file.id, { +- progress: Object.assign({}, this.getFile(file.id), { ++ progress: {","nice, just noticed this today as well :)",2018-03-12 12:01:33 +584,"@@ -647,6 +647,49 @@ describe('src/Core', () => { + } + }) + ++ it('should not allow a dupicate file, a file with the same id', () => { ++ const core = new Core() ++ core.addFile({ ++ source: 'jest', ++ name: 'foo.jpg', ++ type: 'image/jpeg', ++ data: new File([sampleImage], { type: 'image/jpeg' }) ++ }) ++ expect(() => {","Parentheses typo, this test is never failing. +Should be: + + expect(() => { + core.addFile({ + source: 'jest', + name: 'foo.jpg', + type: 'image/jpeg', + data: new File([sampleImage], { type: 'image/jpeg' }), + meta: { + notARelativePath: 'folder/a' + } + }) + }) + .toThrow('Cannot add the duplicate file \'foo.jpg\', it already exists') + +Same on line 707.",2019-08-23 22:58:10 +888,"@@ -65,10 +65,9 @@ exports.getIsFolder = (item) => { + return !item.file_type + } + +-exports.getItemName = (item) => { +- const start = moment(item.start_time || item.recording_start) +- .clone() +- .format('YYYY-MM-DD, kk:mm') ++exports.getItemName = (item, userResponse) => { ++ const start = moment.tz(item.start_time || item.recording_start, userResponse.timezone || 'UTC') ++ .format('YYYY-MM-DD, HH:mm')","we display datetimes in user's timezone preferably. +Timestamp is also updated to use standard hours, rather than 24 hour time from 1 to 24 (HH instead of kk)",2020-09-11 21:05:13 +190,"@@ -65,3 +67,82 @@ describe('File upload with DragDrop + Tus, DragDrop + XHRUpload, i18n translated + // }) + // }) + // }) ++ ++describe.only('XHRUpload with `limit`', () => {",need to remove the `.only` before merge,2018-01-08 09:23:58 +674,"@@ -65,6 +65,7 @@ + ""@uppy/utils"": ""file:packages/@uppy/utils"", + ""@uppy/webcam"": ""file:packages/@uppy/webcam"", + ""@uppy/xhr-upload"": ""file:packages/@uppy/xhr-upload"", ++ ""adm-zip"": ""0.4.13"",","In the past we've put build dependencies in `devDependencies` in the root repo, and only put the uppy packages in `dependencies`. it doesn't make a difference functionally but for consistency's sake it would be best to move this to devDependencies too",2020-02-05 11:04:43 +33,"@@ -65,6 +66,10 @@ module.exports = class Transloadit extends Plugin { + }) + + this.core.setState({ files }) ++ ++ if (this.opts.wait) { ++ return this.beginWaiting() ++ } + }).catch((err) => { + this.core.emit('informer', '⚠️ Transloadit: Could not create assembly', 'error', 0)","Would be cool if the error was accessible somehow. Maybe behind a `more details` link for the user. But i realize that goes beyond the scope of this PR, so maybe we can just dump it to the `console.error` for now short of having sth like that?",2017-04-11 11:08:33 +788,"@@ -65,7 +65,11 @@ class AddFiles extends Component { + + renderMyDeviceAcquirer = () => { + return ( +-
    ++
    { + return ( +-
    ++
    { ++ handleComplete = ({ failed }) => { + if (this.opts.closeAfterFinish && failed.length === 0) { + // All uploads are done + this.requestCloseModal() + } + } + ++ _openFileEditorWhenSingleFileAdded = (file) => {","not totally sure about this behaviour when adding multiple files ... it looks like this would only open the file editor for _one_ of the files? + +maybe it should auto open for each file in turn? but then we'd probably need a ""skip all"" button in the UI in case users don't want to tweak metadata for a folder of 1000 photos.",2020-12-09 16:11:20 +692,"@@ -651,7 +645,7 @@ module.exports = class Dashboard extends Plugin { + superFocusOnEachUpdate = () => { + const isFocusInUppy = this.el.contains(document.activeElement) + // When focus is lost on the page (== focus is on body for most browsers, or focus is null for IE11) +- const isFocusNowhere = document.activeElement === document.querySelector('body') || document.activeElement === null ++ const isFocusNowhere = document.activeElement === document.body || document.activeElement === null","I'm _pretty_ sure this warning is a bug in the compat lint and not actually accurate, but I guess it doesn't matter in this case :)",2020-03-09 14:41:37 +522,"@@ -656,6 +657,52 @@ module.exports = class Dashboard extends Plugin { + this.superFocusOnEachUpdate() + } + ++ startUpload = (ev) => { ++ this.uppy.upload().catch((err) => { ++ // Log error. ++ this.uppy.log(err.stack || err.message || err) ++ }) ++ } ++ ++ cancelUpload = (fileID) => { ++ this.uppy.removeFile(fileID) ++ } ++ ++ saveFileCard = (meta, fileID) => { ++ this.uppy.setFileMeta(fileID, meta) ++ this.toggleFileCard() ++ } ++ ++ _attachRenderFunctionToTarget = (target) => { ++ const plugin = this.uppy.getPlugin(target.id) ++ return { ++ ...target, ++ icon: plugin.icon || this.opts.defaultPickerIcon, ++ render: plugin.render ++ } ++ } ++ ++ _isTargetSupported = (target) => { ++ const plugin = this.uppy.getPlugin(target.id) ++ // If the plugin does not provide a `supported` check, assume the plugin works everywhere. ++ if (typeof plugin.isSupported !== 'function') { ++ return true ++ } ++ return plugin.isSupported() ++ } ++ ++ _getAcquirers = memoize((targets) => { ++ return targets ++ .filter(target => target.type === 'acquirer' && this._isTargetSupported(target)) ++ .map(this._attachRenderFunctionToTarget) ++ }) ++ ++ _getProgressIndicators = memoize((targets) => { ++ return targets ++ .filter(target => target.type === 'progressindicator') ++ .map(this._attachRenderFunctionToTarget) ++ })","Is using `memoize` here basically sort of a hack, because we can’t get access to props, since render is passed the whole `state` in this case?",2019-06-24 13:01:13 +966,"@@ -658,6 +658,18 @@ module.exports = class Dashboard extends Plugin { + } + } + ++ handleRestored = () => { ++ // Hide and show files to trigger re-render, so that ++ // VirtualList mounts FileItems again and they emit `thumbnail:request` ++ // Otherwise thumbnails are broken or missing after Golden Retriever restores files ++ if (this.opts.showSelectedFiles) { ++ this.setOptions({ showSelectedFiles: false }) ++ setTimeout(() => { ++ this.setOptions({ showSelectedFiles: true }) ++ }, 4) ++ } ++ } ++",@goto-bus-stop is there a more sane way to trigger re-render of VirtualList to get thumnails re-created? 🤔 ,2020-12-18 12:40:15 +675,"@@ -66,8 +66,10 @@ en_US.strings = { + loading: 'Loading...', + logOut: 'Log out', + myDevice: 'My Device', ++ noDuplicates: 'Cannot add the duplicate file %{fileName}, it already exists',",this one should also have quotes i guess :),2020-02-10 09:56:45 +477,"@@ -675,7 +675,7 @@ a.uppy-Dashboard-poweredBy { + float: left; + margin: 5px $rl-margin; + width: calc(33.333% - #{$rl-margin} - #{$rl-margin}); +- height: 200px; ++ height: 216px;","```suggestion + height: 215px; +``` +",2019-05-24 09:45:49 +785,"@@ -68,10 +69,15 @@ module.exports = class Dashboard extends Plugin { + saveChanges: 'Save changes', + cancel: 'Cancel', + myDevice: 'My Device', +- dropPaste: 'Drop files here, paste or %{browse}', +- dropPasteImport: 'Drop files here, paste, %{browse} or import from:', ++ dropPasteFiles: enUS.dropPasteFiles, ++ dropPasteFolders: enUS.dropPasteFolders, ++ dropPasteBoth: enUS.dropPasteBoth, ++ dropPasteImportFiles: enUS.dropPasteImportFiles, ++ dropPasteImportFolders: enUS.dropPasteImportFolders, ++ dropPasteImportBoth: enUS.dropPasteImportBoth,","The `@uppy/locales/en_US` file is generated from the default strings in all the plugins, so they should actually be written out here instead of in `en_US.js`. You can then run `npm run build:locale-pack` to update the en_US file.",2020-06-24 11:25:26 +440,"@@ -68,6 +73,10 @@ module.exports = function Dashboard (props) { + } + +
    ++
    ++ {props.i18n('dropHint')}",Tiny style nitpick: I’d call it `uppy-Dashboard-dropFilesHereHint`.,2019-04-16 14:34:34 +532,"@@ -68,7 +68,7 @@ svg.UppyIcon.retry { + } + + +-// Svg styles that depend upon the state of the file.",Seems grammatically there’s no difference? https://english.stackexchange.com/questions/34291/depend-upon-or-depend-on ;),2019-06-27 16:32:36 +799,"@@ -681,6 +681,8 @@ module.exports = class Tus extends Plugin { + this.uppy.on('reset-progress', this.handleResetProgress) + + if (this.opts.autoRetry) { ++ this.uppy.log('[Tus] The `autoRetry` option may be removed in Uppy 2.0. See https://github.com/transloadit/uppy/pull/2347 for alternatives.', 'warning')",maybe not do this because autoretry is the default,2020-06-29 15:26:39 +259,"@@ -69,13 +70,16 @@ module.exports = class FileInput extends Plugin { + zIndex: -1 + } + ++ const restrictions = this.uppy.opts.restrictions ++ + return
    + val).join('-') ++ let id = 'uppy' ++ if (typeof file.name === 'string') { ++ id += '-' + encodeFilename(file.name.toLowerCase()) ++ } ++ ++ if (file.type !== undefined) { ++ id += '-' + file.type ++ } ++ ++ if (file.meta && typeof file.meta.relativePath === 'string') { ++ id += '-' + encodeFilename(file.meta.relativePath.toLowerCase()) ++ } ++ ++ if (file.data.size !== undefined) { ++ id += '-' + file.data.size ++ } ++ if (file.data.lastModified !== undefined) { ++ id += '-' + file.data.lastModified ++ } ++ ++ return id","Wow, impressive it's faster than the previous solution! +Maybe let's add a comment explaining why we went for this solution? I imagine I'd look at it and try to rewrite it in a more concise way.",2019-12-01 16:06:48 +77,"@@ -7,23 +7,48 @@ const _getName = (id) => { + } + + module.exports = class Provider { +- constructor (opts) { ++ constructor (core, opts) { ++ this.core = core + this.opts = opts + this.provider = opts.provider + this.id = this.provider + this.authProvider = opts.authProvider || this.provider + this.name = this.opts.name || _getName(this.id) ++ ++ this.onReceiveResponse = this.onReceiveResponse.bind(this) ++ } ++ ++ get hostname () { ++ const uppyServer = this.core.state.uppyServer || {} ++ const host = this.opts.host ++ return uppyServer[host] || host ++ } ++ ++ onReceiveResponse (response) { ++ const uppyServer = this.core.state.uppyServer || {} ++ const host = this.opts.host ++ const headers = response.headers ++ // Store the self-identified domain name for the uppy-server we just hit. ++ if (headers.has('i-am') && headers.get('i-am') !== uppyServer[host]) { ++ this.core.setState({ ++ uppyServer: Object.assign({}, uppyServer, { ++ [host]: headers.get('i-am') ++ }) ++ })","The `uppyServer` state key is an object of `[original_hostname]: new_hostname` pairs, in case someone does something like + +```js +uppy.use(GoogleDrive, { host: 'google.my-uppy-server.com' }) +uppy.use(Dropbox, { host: 'dropbox.my-uppy-server.com' }) +``` + +It seems unlikely that anyone would use different uppy-servers for different plugins, but it's _possible_, so this supports it.",2017-07-21 09:54:13 +333,"@@ -7,33 +7,32 @@ set -o nounset + # Set magic variables for current FILE & DIR + __dir=""$(cd ""$(dirname ""${BASH_SOURCE[0]}"")"" && pwd)"" + __kube=""${__dir}"" ++__companion=""$(dirname ""$(dirname ""${__kube}"")"")"" ++# Install kubectl ++curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl",Shall we pin the currently used kubectl and hence make version bumps opt-in vs organic?,2018-08-17 05:14:15 +334,"@@ -7,33 +7,32 @@ set -o nounset + # Set magic variables for current FILE & DIR + __dir=""$(cd ""$(dirname ""${BASH_SOURCE[0]}"")"" && pwd)"" + __kube=""${__dir}"" ++__companion=""$(dirname ""$(dirname ""${__kube}"")"")"" ++# Install kubectl ++curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl ++chmod +x ./kubectl ++mkdir ${HOME}/.local/bin/ ++export PATH=""${HOME}/.local/bin/:$PATH"" ++mv ./kubectl ${HOME}/.local/bin/ ++ + + # Store the new image in docker hub +-docker build --quiet -t transloadit/companion:latest -t transloadit/companion:$TRAVIS_COMMIT .; ++docker build -t kiloreux/uppy-companion:latest -t kiloreux/uppy-companion:$TRAVIS_COMMIT -f packages/@uppy/companion/Dockerfile packages/@uppy/companion;",Transloadit,2018-08-17 05:14:36 +508,"@@ -7,57 +7,73 @@ class FileCard extends Component { + constructor (props) { + super(props) + +- this.meta = {} ++ this.state = {} + +- this.tempStoreMetaOrSubmit = this.tempStoreMetaOrSubmit.bind(this) ++ this.tempStoreMeta = this.tempStoreMeta.bind(this) ++ this.saveOnEnter = this.saveOnEnter.bind(this) + this.renderMetaFields = this.renderMetaFields.bind(this) + this.handleSave = this.handleSave.bind(this) + this.handleCancel = this.handleCancel.bind(this) + } + +- tempStoreMetaOrSubmit (ev) { ++ componentDidMount () { + const file = this.props.files[this.props.fileCardFor] ++ const metaFields = this.props.metaFields || [] ++ ++ const storedMetaData = {} ++ metaFields.forEach((field) => { ++ storedMetaData[field.id] = file.meta[field.id] ++ }) ++ this.setState(storedMetaData) ++ } + ++ saveOnEnter (ev) { + if (ev.keyCode === 13) { ++ const file = this.props.files[this.props.fileCardFor] + ev.stopPropagation() + ev.preventDefault() +- this.props.saveFileCard(this.meta, file.id) +- return ++ this.props.saveFileCard(this.state, file.id) + } ++ } + ++ tempStoreMeta (ev) { + const value = ev.target.value + const name = ev.target.dataset.name +- this.meta[name] = value ++ this.setState({ ++ [name]: value ++ }) ++ } ++ ++ handleSave (ev) { ++ const fileID = this.props.fileCardFor ++ this.props.saveFileCard(this.state, fileID) ++ } ++ ++ handleCancel (ev) { ++ this.setState({})","note this is a noop, it doesn't actually clear state",2019-06-12 08:02:14 +511,"@@ -7,57 +7,73 @@ class FileCard extends Component { + constructor (props) { + super(props) + +- this.meta = {} ++ this.state = {} + +- this.tempStoreMetaOrSubmit = this.tempStoreMetaOrSubmit.bind(this) ++ this.tempStoreMeta = this.tempStoreMeta.bind(this) ++ this.saveOnEnter = this.saveOnEnter.bind(this) + this.renderMetaFields = this.renderMetaFields.bind(this) + this.handleSave = this.handleSave.bind(this) + this.handleCancel = this.handleCancel.bind(this) + } + +- tempStoreMetaOrSubmit (ev) { ++ componentDidMount () { + const file = this.props.files[this.props.fileCardFor] ++ const metaFields = this.props.metaFields || [] ++ ++ const storedMetaData = {} ++ metaFields.forEach((field) => { ++ storedMetaData[field.id] = file.meta[field.id] ++ }) ++ this.setState(storedMetaData) ++ } + ++ saveOnEnter (ev) { + if (ev.keyCode === 13) { ++ const file = this.props.files[this.props.fileCardFor] + ev.stopPropagation() + ev.preventDefault() +- this.props.saveFileCard(this.meta, file.id) +- return ++ this.props.saveFileCard(this.state, file.id) + } ++ } + ++ tempStoreMeta (ev) { + const value = ev.target.value + const name = ev.target.dataset.name +- this.meta[name] = value ++ this.setState({ ++ [name]: value ++ }) ++ } ++ ++ handleSave (ev) { ++ const fileID = this.props.fileCardFor ++ this.props.saveFileCard(this.state, fileID) ++ } ++ ++ handleCancel (ev) { ++ this.setState({}) ++ this.props.toggleFileCard() + } + + renderMetaFields (file) { + const metaFields = this.props.metaFields || [] ++ + return metaFields.map((field, i) => { + return
    + + this.tempStoreMeta(event, field.id)}`, that looks more react-like?",2019-06-12 09:25:23 +991,"@@ -7,6 +7,11 @@ module.exports = class Editor extends Component { + this.imgElement, + this.props.opts.cropperOptions + ) ++ this.imgElement.addEventListener('crop', (ev) => { ++ this.rotateRange.value = ev.detail.rotate ++ this.rotateRange.parentNode ++ .setAttribute('aria-label', `${ev.detail.rotate}º`)","Would these be feasible to do using react state updates, vs updating the dom directly?",2021-03-31 09:48:48 +352,"@@ -7,6 +7,8 @@ function DashboardContentTitle (props) { + } + + function PanelTopBar (props) { ++ const notOverFileLimit = props.maxNumberOfFiles !== props.totalFileCount",`props.totalFileCount < props.maxNumberOfFiles` makes the intent a bit more clear I think. And a check to see if maxNumberOfFiles even exists?,2018-09-20 09:35:40 +28,"@@ -7,7 +7,7 @@ module.exports = (props) => { +

    + Please authenticate with ${props.pluginName}
    to select files +

    +- Authenticate ++ Authenticate","🤔 Since this is not a link now, semantically we could turn it into a ` ++ ) ++ } ++ ++ renderDropPasteBrowseTagline = () => { ++ const numberOfAcquirers = this.props.acquirers.length ++ const browseFiles = this.renderBrowseButton(this.props.i18n('browseFiles'), this.triggerFileInputClick) ++ const browseFolders = this.renderBrowseButton(this.props.i18n('browseFolders'), this.triggerFolderInputClick) ++ ++ // in order to keep the i18n CamelCase and options lower (as are defaults) we will want to transform a lower ++ // to Camel ++ const lowerBrowseType = this.props.browserUploadType ++ const camelBrowseType = lowerBrowseType.charAt(0).toUpperCase() + lowerBrowseType.slice(1) + + return ( +
    + { + numberOfAcquirers > 0 +- ? this.props.i18nArray('dropPasteImport', { browse }) +- : this.props.i18nArray('dropPaste', { browse }) ++ ? this.props.i18nArray(`dropPasteImport${camelBrowseType}`, { browseFiles, browseFolders }) ++ : this.props.i18nArray(`dropPaste${camelBrowseType}`, { browseFiles, browseFolders })","This is a breaking change, as users with custom strings are still using `%{browse}` and it would no longer be replaced correctly. +I think using `browseFiles` and `browseFolders` as names is the correct approach, but we can maintain backwards compatibility by also providing a value for `browse`: +```suggestion + ? this.props.i18nArray(`dropPasteImport${camelBrowseType}`, { browseFiles, browseFolders, browse: browseFiles }) + : this.props.i18nArray(`dropPaste${camelBrowseType}`, { browseFiles, browseFolders, browse: browseFiles }) +```",2020-06-24 11:28:46 +819,"@@ -86,6 +86,11 @@ class FileCard extends Component { + render () { + const file = this.props.files[this.props.fileCardFor] + ++ let showEditButton ++ this.props.editors.forEach((target) => { ++ showEditButton = this.props.getPlugin(target.id).сanEditFile(file)",❓Questionable way of looping through editors and calling `сanEditFile` to show the edit button. Is there a better way?,2020-07-13 09:11:23 +823,"@@ -86,6 +86,11 @@ class FileCard extends Component { + render () { + const file = this.props.files[this.props.fileCardFor] + ++ let showEditButton ++ this.props.editors.forEach((target) => { ++ showEditButton = this.props.getPlugin(target.id).сanEditFile(file) ++ })","I think the looping stuff is probably the only way, but it could use `.some()` instead of `.forEach()`, so it will also stop looping as soon as it finds a match: +```suggestion + const showEditButton = this.props.editors.some((target) => { + const plugin = this.props.getPlugin(target.id) + plugin.сanEditFile(file) + }) +``` + +(Also this is a minor thing, but I would probably put this entire code in the Dashboard plugin class itself and pass it in as a prop, so you can do `this.props.canEditFile(file)` instead of writing the loop in the render code. Then it doesn't depend directly on other plugins. If we ever end up doing testing for the components it will be easier that way)",2020-07-13 09:36:21 +130,"@@ -867,6 +867,7 @@ class Uppy { + + info (message, type, duration) { + const isComplexMessage = typeof message === 'object' ++ duration = typeof duration === 'undefined' ? 3000 : duration",how about a default parameter instead?,2017-10-24 07:29:41 +215,"@@ -87,11 +87,25 @@ module.exports = class Transloadit extends Plugin { + + getAssemblyOptions (fileIDs) { + const options = this.opts ++ ++ const normalizeAssemblyOptions = (assemblyOptions) => { ++ const globalMeta = this.uppy.getState().meta ++ // Include global metadata as fields. Works great together with the Form plugin :) ++ if (assemblyOptions.fields === true) { ++ assemblyOptions.fields = Object.assign({}, globalMeta) ++ } ++ if (!assemblyOptions.fields) { ++ assemblyOptions.fields = {} ++ } ++ return assemblyOptions ++ } ++ + return Promise.all( + fileIDs.map((fileID) => { + const file = this.uppy.getFile(fileID) + const promise = Promise.resolve() + .then(() => options.getAssemblyOptions(file, options)) ++ .then(normalizeAssemblyOptions)",Nitpicking here: is `normalizeAssemblyOptions` a good name when it mostly adds `fields` to an assembly?,2018-02-06 20:36:53 +301,"@@ -87,15 +87,7 @@ + ""lint:fix"": ""npm run lint -- --fix"", + ""lint"": ""eslint . --cache"", + ""lint-staged"": ""lint-staged"", +- ""release:major"": ""env SEMANTIC=major npm run release"", +- ""release:minor"": ""env SEMANTIC=minor npm run release"", +- ""release:patch"": ""env SEMANTIC=patch npm run release"", +- ""replace:versions"": ""replace-x -r 'uppy/v\\d+\\.\\d+\\.\\d+/dist' \""uppy/v$npm_package_version/dist\"" ./examples/ README.md bin/upload-to-cdn.sh website/src/examples/ website/src/docs/ website/themes/uppy/layout/ --exclude=node_modules"", +- ""replace:versions:commit"": ""git commit -m \""Change Uppy version references to v$npm_package_version\"" ./examples/ README.md bin/upload-to-cdn.sh website/src/examples/ website/src/docs/ website/themes/uppy/layout/"", +- ""release:tag"": ""npm version ${SEMANTIC:-patch} -m \""Release %s\"""", +- ""release:build"": ""npm-run-all clean build release:copy-uppy-readme"", +- ""release:copy-uppy-readme"": ""cp README.md packages/uppy/README.md"", +- ""release"": ""npm-run-all release:tag release:build replace:versions replace:versions:commit && git push && git push --tags && npm publish"", ++ ""release"": ""./bin/release"", + ""start:server"": ""node bin/start-server"",","Soooo, how do we release a patch or minor now? :)",2018-06-21 13:56:06 +994,"@@ -87,6 +88,9 @@ module.exports = () => { + .use(ScreenCapture, { target: Dashboard }) + .use(Form, { target: '#upload-form' }) + .use(ImageEditor, { target: Dashboard }) ++ .use(DomTarget, {","```suggestion + .use(DropTarget, { +```",2021-03-31 11:54:45 +216,"@@ -87,7 +87,6 @@ class Uppy { + this.upload = this.upload.bind(this) + + this.emitter = ee() +- this.on = this.emitter.on.bind(this.emitter)","`on` likely still needs a bind, similar to `this.resetProgress = this.resetProgress.bind(this)` correct?",2018-02-07 09:22:07 +140,"@@ -87,9 +87,9 @@ module.exports = class Plugin { + this.el = plugin.render(this.core.state) + targetElement.appendChild(this.el) + +- this.target = targetElement ++ this.target = this.el","I'm not sure what the effects of this change would be. if we do this we could remove `this.target` entirely and use `this.el` everywhere instead. + +It seems like these two lines could stay the same. Or is there a reason to change this here that I'm missing?",2017-11-17 16:11:38 +520,"@@ -88,12 +88,11 @@ class TransloaditAssembly extends Emitter { + + socket.on('assembly_upload_finished', (file) => { + this.emit('upload', file) +- this._fetchStatus({ diff: false }) ++ this.status.uploads.push(file) + }) + + socket.on('assembly_uploading_finished', () => { + this.emit('executing') +- this._fetchStatus({ diff: false })","uploading_finished and upload_meta_data_extracted can fire very quickly after another, and there is not much difference in the Assembly status that's useful to us. I kept only the Assembly fetch after metadata is extracted, which ensures that we'll have all the correct `uploads.*.meta` properties on the client side.",2019-06-24 10:19:20 +296,"@@ -88,5 +94,8 @@ module.exports = class RequestClient { + .then(this.onReceiveResponse) + // @todo validate response status before calling json + .then((res) => res.json()) ++ .catch((err) => { ++ throw new Error(`Could not detele ${this._getUrl(path)}. ${err}`)",s/detele/delete,2018-06-11 09:08:57 +758,"@@ -88,7 +88,7 @@ class Uploader { + this._paused = true + if (this.tus) { + const shouldTerminate = !!this.tus.url +- this.tus.abort(shouldTerminate) ++ this.tus.abort(shouldTerminate).catch(() => {})","The `abort` function now returns a Promise. And if `shouldTerminate` is true, this Promise can be rejected. So, to avoid a unhandled promise rejection, I added a dummy handler. Since a possible error also wasn't handled before, I think it's OK to not handle it in this case as well.",2020-05-03 15:44:59 +404,"@@ -88,7 +88,7 @@ module.exports.app = (options = {}) => { + app.get('/:providerName/logout', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.logout) + app.get('/:providerName/authorized', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.authorized) + app.get('/:providerName/list/:id?', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.list) +- app.post('/:providerName/get/:id', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.get) ++ app.post('/:providerName/get/:id', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.get)",do you mind sharing what is the reason for this change?,2019-02-24 15:55:27 +295,"@@ -886,16 +886,22 @@ class Uppy { + * @param {object} instance The plugin instance to remove. + */ + removePlugin (instance) { +- const list = this.plugins[instance.type] ++ this.emit('plugin-removed', instance)","the event name suggests it's already been done, but actually the plugin is _about_ to be removed. It does need to be emitted at this time but maybe we can name it differently (`remove-plugin`, `plugin-remove`, idk)",2018-06-11 08:58:36 +451,"@@ -89,10 +89,19 @@ Here are some highlights on what we’ve managed to delived in the Uppy Month: + - Works great on mobile + - Works great with Transloadit. Works great without + +-- knows about encoding ++We also left two features ""behind"": ++ ++> Offering sugared shortcuts for novice users (presets) ++ ++We felt Uppy is straightforward enough to use, presets could end up making this less clear. Robodog does offer less boilerplatey integrations, but this was done as a wrapper instead of a preset. ++ ++> Themable UI with a beautiful default ++ ++Instead of going for `{ theme: 'dark' }`, we only offer theming via CSS. It is of course very feasible to create a `dark.css` file, and maybe we can come up with a section on the site for easily sharing and distributing such files, but we let go of this desire for 1.0. ++ ++It's not :100:, but for a 3 year gameplan, we are very happy with this result! + ","Not sure if we even need this section, we could then as well say we don’t have Box and Google Photos support. Yeah, I know those things were on the list on the website, but.",2019-04-24 13:56:21 +452,"@@ -89,10 +89,19 @@ Here are some highlights on what we’ve managed to delived in the Uppy Month: + - Works great on mobile + - Works great with Transloadit. Works great without + +-- knows about encoding ++We also left two features ""behind"": ++ ++> Offering sugared shortcuts for novice users (presets) ++ ++We felt Uppy is straightforward enough to use, presets could end up making this less clear. Robodog does offer less boilerplatey integrations, but this was done as a wrapper instead of a preset. ++ ++> Themable UI with a beautiful default ++ ++Instead of going for `{ theme: 'dark' }`, we only offer theming via CSS. It is of course very feasible to create a `dark.css` file, and maybe we can come up with a section on the site for easily sharing and distributing such files, but we let go of this desire for 1.0. ++ ++It's not :100:, but for a 3 year gameplan, we are very happy with this result! + + ## What’s next for Uppy? + +-We are releasing 1.0 as Uppy has matured into a full-featured capable file uploader. The work, however, is never done — there are suggestions coming in from the community and the team every day. And we are already [planning some features and bug fixes for 1.1](https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#11). ++Does this mean Uppy is perfect? Nope! There are [issues](https://github.com/transloadit/uppy/issues), items in our backlog, and we are already [planning Uppy 1.1](https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#11). We want to release a WordPress plugin, add image cropping, and more, but we are releasing 1.0 today because it contains the features that we set out to implement. They are all documented and we don't expect their APIs to change. Uppy has seen serious usage by a seriously large community and by various serious enterprises, and with 1.0 we're also signaling to you: Hey, we take it serious and we won't be swapping things from underneath your app just like that. And if you don't have Uppy powering your file uploads yet, now is the best time to give it a shot. + ","> we don't expect their APIs to change + +🤔 ",2019-04-24 13:57:42 +65,"@@ -89,6 +89,18 @@ module.exports = class Plugin { + } + } + ++ setMetaFromTargetForm () { ++ const el = findDOMElement(this.opts.target) ++ const formMetaData = getMetaFromForm(el) ++ if (formMetaData) { ++ this.core.log('Adding metadata from form:') ++ this.core.log(formMetaData) ++ this.core.setMeta(formMetaData) ++ } else { ++ this.core.log('Couldn’t extract metadata from form') ++ } ++ }","I'm not sure about putting `setMetaFromTargetForm` on the Plugin class, since it's not for use by every plugin…Maybe the plugins could manually do + +```js +this.core.setMeta(getMetaFromForm(this.target)) +``` + +in their `install()` methods? that's not a _lot_ of code to duplicate.",2017-06-29 11:48:07 +756,"@@ -89,6 +90,6 @@ + ""test:watch"": ""npm test -- --watch"" + }, + ""engines"": { +- ""node"": "">=6.0.0"" ++ ""node"": "">=10.0.0""",i would do this in a separate PR because it also needs a travis.yml update (and maybe docs?),2020-04-29 12:35:03 +468,"@@ -9,10 +9,20 @@ + ""window"": true, + ""hexo"": true + }, +- ""plugins"": [""jest"", ""compat""], ++ ""plugins"": [""jest"", ""compat"", ""jsdoc""], + ""rules"": { + ""jsx-quotes"": [""error"", ""prefer-double""], +- ""compat/compat"": [""error""] ++ ""compat/compat"": [""error""], ++ ++ ""jsdoc/check-alignment"": [""error""], ++ ""jsdoc/check-examples"": [""error""], ++ ""jsdoc/check-indentation"": [""error""], ++ ""jsdoc/check-param-names"": [""error""], ++ ""jsdoc/check-syntax"": [""error""], ++ ""jsdoc/check-tag-names"": [""error""], ++ ""jsdoc/check-types"": [""error""], ++ ""jsdoc/newline-after-description"": [""error""], ++ ""jsdoc/valid-types"": [""error""] + },",Cool! I wonder if this will result in many errors in other files that use JSDoc?,2019-05-21 13:25:12 +806,"@@ -9,11 +9,29 @@ const instagram = require('./instagram') + const instagramGraph = require('./instagram/graph') + const facebook = require('./facebook') + const onedrive = require('./onedrive') ++const zoom = require('./zoom') + const { getURLBuilder } = require('../helpers/utils') + const logger = require('../logger') + // eslint-disable-next-line + const Provider = require('./Provider') + ++// leave here for now until Purest Providers gets updated with Zoom provider",I opened a pr here https://github.com/simov/purest-providers/pull/1 but it doesn't look like Purest providers has been updated in a few years. this was required to get the auth flow working,2020-07-02 21:43:10 +455,"@@ -9,13 +9,12 @@ + ""titleBar.activeForeground"": ""#ffffff"", + ""titleBar.activeBackground"": ""#ff009d"", + }, +- ""files.exclude"": { ++ ""search.exclude"": { + ""website/public/"": true,","sorry, I meant to commit this to master",2019-04-25 11:18:31 +521,"@@ -9,14 +9,40 @@ module.exports = (props) => { + { 'uppy-Dashboard-files--noFiles': noFiles } + ) + ++ const fileProps = { ++ // FIXME This is confusing, it's actually the Dashboard's plugin ID ++ id: props.id, ++ error: props.error, ++ // TODO move this to context ++ i18n: props.i18n, ++ log: props.log, ++ info: props.info, ++ // features ++ acquirers: props.acquirers, ++ resumableUploads: props.resumableUploads, ++ individualCancellation: props.individualCancellation, ++ // visual options ++ hideRetryButton: props.hideRetryButton, ++ hidePauseResumeCancelButtons: props.hidePauseResumeCancelButtons, ++ showLinkToFileUploadResult: props.showLinkToFileUploadResult, ++ isWide: props.isWide, ++ metaFields: props.metaFields, ++ // callbacks ++ retryUpload: props.retryUpload, ++ pauseUpload: props.pauseUpload, ++ cancelUpload: props.cancelUpload, ++ toggleFileCard: props.toggleFileCard, ++ removeFile: props.removeFile ++ } ++","Are you picking these specific props, so that only the ones really used in the component are passed, and `shallowEqual` works better?",2019-06-24 12:59:13 +225,"@@ -9,40 +9,40 @@ The Transloadit plugin can be used to upload files to [Transloadit](https://tran + + [Try it live](/examples/transloadit/) + +-The Transloadit plugin uses the [Tus plugin](/docs/tus) for the uploading itself. +-To upload files to Transloadit directly, both the Tus and Transloadit plugins must be used: +- + ```js +-// The `resume: false` option _must_ be provided to the Tus plugin. +-uppy.use(Tus, { +- resume: false +-}) + uppy.use(Transloadit, { +- // Transloadit plugin options ++ service: 'https://api2.transloadit.com', ++ waitForEncoding: false, ++ waitForMetadata: false, ++ importFromUploadURLs: false, ++ alwaysRunAssembly: false, ++ params: null, ++ signature: null, ++ fields: {} + }) + ``` + +-NB: It is not required to use the `Tus` plugin if [importFromUploadURLs](#importFromUploadURLs) is enabled. ++As of Uppy 0.24 the Transloadit plugin includes the [Tus](/docs/tus) plugin to handle the uploading, so you no longer have to add it manually.","Writing the version number here because this PR will probably be merged before we release the change, and it would be confusing otherwise … versioned docs would be rad, but probably a lot of work!",2018-02-12 14:08:15 +165,"@@ -9,7 +13,10 @@ module.exports = (props) => { + type=""file"" + name=""files[]"" + multiple=""true"" +- onchange=${props.handleInputChange} />` ++ onchange=${props.handleInputChange} ++ ref=${(input) => { ++ inputEl = input ++ }} />`","this `` element was made a separate element so that we could store a reference to it in the `input` variable, but that is not necessary when we have `ref`. it could be inlined in the `${input}` line below.",2017-12-13 21:34:54 +639,"@@ -90,6 +90,12 @@ + margin-right: 12px; + } + ++.uppy-Webcam-recordingLength { ++ position: absolute; ++ right: 20px; ++ color: $gray-600;","```suggestion +color: $gray-600; +font-family: SFMono-Regular, Menlo, Monaco, Consolas, ""Liberation Mono"", ""Courier New"", monospace; +``` + +How about using a mono-spaced font, so the numbers don’t jump when they change? They jump slightly for me in Firefox on MacOS.",2019-11-26 17:56:04 +208,"@@ -90,6 +91,19 @@ module.exports = class XHRUpload extends Plugin { + formPost.append(item, file.meta[item]) + }) + ++ let data = opts.data ++ if (typeof opts.data === 'function') { ++ data = opts.data(file) ++ } ++ ++ if (data != null) { ++ (typeof data === 'object') ++ ? Object.keys(data).forEach((key) => { ++ formPost.append(key, data[key]) ++ })","What's wrong with a if here? Also, `Object.entries` is more appropriate if you need both the key and the value. +```js +Object.entries(data).forEach(entry => formPost.append(...entry)) +``` +You will probably want to deal with nested objects somehow (probably worth throwing since it's really an invalid behavior and will result in `""[object Object]""` being sent)",2018-02-01 10:57:15 +209,"@@ -90,6 +91,19 @@ module.exports = class XHRUpload extends Plugin { + formPost.append(item, file.meta[item]) + }) + ++ let data = opts.data ++ if (typeof opts.data === 'function') { ++ data = opts.data(file) ++ } ++ ++ if (data != null) { ++ (typeof data === 'object') ++ ? Object.keys(data).forEach((key) => { ++ formPost.append(key, data[key]) ++ }) ++ : formPost.append('data', data)","I think we should just require that `data` is an object, and not allow single values.",2018-02-01 13:53:16 +744,"@@ -90,7 +96,13 @@ module.exports = class XHRUpload extends Plugin { + * @param {XMLHttpRequest | respObj} response the response object (XHR or similar) + */ + getResponseError (responseText, response) { +- return new Error('Upload error') ++ let error = new Error('Upload error') ++ ++ if (isNetworkError(response)) { ++ error = new NetworkError(error)",should we be passing the `xhr` object to the `NetworkError` here as well?,2020-04-17 12:53:02 +505,"@@ -909,6 +911,8 @@ class Uppy { + throw new Error(msg) + } + ++ this.log(`Using ${pluginId} v${Plugin.VERSION}`)","might want to check if it exists, most userland plugins won't have it for example",2019-06-07 12:06:53 +348,"@@ -91,7 +91,7 @@ Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly + + - [Uppy](https://uppy.io/docs/uppy/) — full list of options, methods, and events. + - [Plugins](https://uppy.io/docs/plugins/) — list of Uppy plugins and their options. +-- [Companion](https://uppy.io/docs/companion/) — setting up and running an Uppy Companion instance, which adds support for Instagram, Dropbox, Google Drive and remote urls. ++- [Companion](https://uppy.io/docs/companion/) — setting up and running an Companion instance, which adds support for Instagram, Dropbox, Google Drive and remote urls.",`s/an Companion/a Companion/`,2018-09-03 12:32:37 +646,"@@ -923,7 +933,9 @@ module.exports = class Dashboard extends Plugin { + this.uppy.use(ThumbnailGenerator, { + id: `${this.id}:ThumbnailGenerator`, + thumbnailWidth: this.opts.thumbnailWidth, +- waitForThumbnailsBeforeUpload: this.opts.waitForThumbnailsBeforeUpload ++ waitForThumbnailsBeforeUpload: this.opts.waitForThumbnailsBeforeUpload, ++ // If we don't block on thumbnails, we can lazily generate them ++ lazy: !this.opts.waitForThumbnailsBeforeUpload","Should we add a warning to the ThumbnailGenerator that if `{ waitForThumbnailsBeforeUpload: true, lazy: true }`, - then thumbnails will never get generated? + +Otherwise I'd probably remove the .lazy option altogether. Cause: +`lazy: !this.opts.waitForThumbnailsBeforeUpload` is the most common use case, +`{ waitForThumbnailsBeforeUpload: true, lazy: true }` won't work, and +`{ waitForThumbnailsBeforeUpload: false, lazy: false }` - is valid, but I can't see the use case.",2019-12-01 19:42:24 +380,"@@ -93,20 +93,58 @@ module.exports.getURLBuilder = (options) => { + } + + /** ++ * Ensure that a user-provided `secret` is 32 bytes long (the length required ++ * for an AES256 key) by hashing it with SHA256. + * +- * @param {*} input +- * @param {string} secret ++ * @param {string|Buffer} secret ++ */ ++function createSecret (secret) { ++ const hash = crypto.createHash('sha256') ++ hash.update(secret) ++ return hash.digest() ++} ++ ++/** ++ * Create an initialization vector for AES256. ++ * ++ * @return {Buffer} ++ */ ++function createIv () { ++ return crypto.randomBytes(16) ++} ++ ++/** ++ * Encrypt a buffer or string with AES256 and a random iv. ++ * ++ * @param {string} input ++ * @param {string|Buffer} secret ++ * @return {string} Ciphertext as a hex string, prefixed with 32 hex characters containing the iv. + */ + module.exports.encrypt = (input, secret) => { +- const cipher = crypto.createCipher('aes256', secret) +- let encrypted = cipher.update(input, 'utf8', 'hex') ++ const iv = createIv() ++ const cipher = crypto.createCipheriv('aes256', createSecret(secret), iv) ++ let encrypted = iv.toString('hex') ++ encrypted += cipher.update(input, 'utf8', 'hex') + encrypted += cipher.final('hex') + return encrypted + } + ++/** ++ * Decrypt an iv-prefixed or string with AES256. The iv should be in the first 32 hex characters. ++ * ++ * @param {string} encrypted ++ * @param {string|Buffer} secret ++ * @return {string} Decrypted value. ++ */ + module.exports.decrypt = (encrypted, secret) => { +- var decipher = crypto.createDecipher('aes256', secret) +- var decrypted = decipher.update(encrypted, 'hex', 'utf8') ++ // Need at least 32 chars for the iv ++ if (encrypted.length < 32) { ++ throw new Error('Invalid encrypted value. Maybe it was generated with an old Companion version?') ++ } ++ ++ const iv = Buffer.from(encrypted.slice(0, 32), 'hex') ++ const decipher = crypto.createDecipheriv('aes256', createSecret(secret), iv) ++ let decrypted = decipher.update(encrypted.slice(32), 'hex', 'utf8')",shouldn't it be `encrypted.slice(16)`? Since it's `<16 random bytes> + encryption`?,2018-11-25 20:46:52 +537,"@@ -93,8 +106,72 @@ class CompanionService { + } + } + ++const express = require('express') ++class StaticServerService { ++ constructor ({ folders, staticServerPort = 4567 }) { ++ this.folders = folders ++ this.port = staticServerPort ++ } ++ ++ async onPrepare () { ++ if (!this.folders) return ++ ++ this.app = express() ++ ++ for (const desc of this.folders) { ++ this.app.use(desc.mount, express.static(desc.path)) ++ } ++ ++ const listen = promisify(this.app.listen.bind(this.app)) ++ ++ this.server = await listen(this.port) ++ } ++ ++ async onComplete () { ++ if (this.server) { ++ const close = promisify(this.server.close.bind(this.server)) ++ await close() ++ } ++ this.app = null ++ } ++} ++ ++const tus = require('tus-node-server')","`master.tus.io` is `tusd` and that is the golden up-to-date tus integration, so we are loosing a bit of that here. `tus-node-server` is outdated, according to Marius. But I see the benefit of not relying on `master.tus.io` of course.",2019-07-01 16:48:28 +121,"@@ -934,7 +942,15 @@ class Uppy { + * + * @return {Promise} + */ +- upload (forceUpload) { ++ upload () { ++ if (!this.plugins.uploader) { ++ this.log('No uploader type plugins are used', 'warning') ++ } ++ ++ if (Object.keys(this.state.files).length === 0) { ++ this.log('No files have been added', 'warning') ++ }","We could do this for now, but this is not always a mistake (eg. transloadit plugin w/ an assembly that imports from somewhere). ",2017-09-30 22:02:14 +875,"@@ -94,32 +94,32 @@ exports.getMimeType = (item) => { + } + + exports.getId = (item) => { +- if (item.file_type && item.file_type === 'TIMELINE') { +- return `${encodeURIComponent(item.meeting_id)}__TIMELINE` ++ if (item.file_type && item.file_type === 'CC') { ++ return `${encodeURIComponent(item.meeting_id)}__CC__${encodeURIComponent(item.recording_start)}`",we do this to differentiate between the multiple cc files for when the recording is stopped / restarted multiple times within a single meeting ,2020-09-04 16:54:12 +95,"@@ -95,6 +103,10 @@ module.exports = class Plugin { + } + } + ++ focus () { ++ return ++ }",Do we need `focus` for something after all?,2017-09-07 19:04:36 +91,"@@ -95,7 +95,7 @@ class Uppy { + meta: Object.assign({}, this.opts.meta), + info: { + isHidden: true, +- type: '', ++ type: 'info', + msg: ''",This property name was changed to `message` further down but not here,2017-08-28 08:02:35 +450,"@@ -96,5 +103,41 @@ module.exports = class Client { + getAssemblyStatus (url) { + return fetch(url) + .then((response) => response.json()) ++ .catch((err) => this._reportError(err, { url })) ++ } ++ ++ submitError (err, { endpoint, instance, assembly }) { ++ return fetch('https://status.transloadit.com/client_error', { ++ method: 'post', ++ body: JSON.stringify({ ++ endpoint, ++ instance, ++ assembly_id: assembly, ++ ip: null, // can't this just be done by statuspage? ++ agent: typeof navigator !== 'undefined' ? navigator.userAgent : '',",can we send the Transloadit-Client along with this?,2019-04-24 09:24:44 +449,"@@ -96,5 +103,41 @@ module.exports = class Client { + getAssemblyStatus (url) { + return fetch(url) + .then((response) => response.json()) ++ .catch((err) => this._reportError(err, { url })) ++ } ++ ++ submitError (err, { endpoint, instance, assembly }) { ++ return fetch('https://status.transloadit.com/client_error', { ++ method: 'post', ++ body: JSON.stringify({ ++ endpoint, ++ instance, ++ assembly_id: assembly, ++ ip: null, // can't this just be done by statuspage? ++ agent: typeof navigator !== 'undefined' ? navigator.userAgent : '', ++ error: err.message","do we only have a string error, no type or constant or other payload that we can use to more easily identify them?",2019-04-24 09:24:33 +400,"@@ -96,6 +100,10 @@ const resultPromise = transloadit.upload(files, { + template_id: '' + } + }) ++resultPromise.then((bundle) => { ++ bundle.transloadit // Array of Assembly statuses ++ bundle.results // Array of all Assembly results ++}) + ``` + ",👍 ,2019-02-04 20:49:41 +114,"@@ -96,6 +97,16 @@ module.exports = class Tus10 extends Plugin { + updatedFiles[file] = updatedFile + }) + this.core.setState({files: updatedFiles}) ++ return ++ case 'retryAll': ++ inProgressUpdatedFiles.forEach((file) => { ++ const updatedFile = Object.assign({}, updatedFiles[file], { ++ isPaused: false, ++ error: null ++ }) ++ updatedFiles[file] = updatedFile ++ }) ++ this.core.setState({files: updatedFiles})","Ye, this only touches core. I think all of these `case`s would make more sense to do in core, controlled by events. (`core:pause-all`, `core:resume-all`, `core:retry-all`) Same for `case 'toggle':`, which seems to respond to `core:upload-pause`.",2017-09-29 14:14:44 +668,"@@ -96,7 +96,7 @@ const uppy = Uppy({ + + You can also provide your own logger object: it should expose `debug`, `warn` and `error` methods, as shown in the examples below. + +-By default `logger` is set to `nullLogger`, which does nothing: ++Here’s an example of `logger` that does nothing:","```suggestion +Here’s an example of a `logger` that does nothing: +```",2020-01-20 12:33:48 +533,"@@ -96,9 +96,18 @@ module.exports = class AwsS3Multipart extends Plugin { + createMultipartUpload (file) { + this.assertHost() + ++ let metadata = {} ++ ++ Object.keys(file.meta).map(key => { ++ if (file.meta[key] !== null) {","I think it'd be best if we also ignored `undefined` here, else the toString() line will crash: +```suggestion + if (file.meta[key] != null) { +```",2019-07-01 08:42:59 +977,"@@ -979,6 +979,13 @@ class Uppy { + } + }) + ++ // If file is a google doc uploaded by companion ++ // file.size is null ++ if (data.bytesTotal === data.bytesUploaded && !file.size) {","some nitpicks 😇 +you've actually addressed a broader issue here, as photos from instagram and facebook also don't have a size. so we can be a bit more accurate in the comment by mentioning remote providers in general: + +```suggestion + // Remote providers sometimes don't tell us the file size, + // but we can know how many bytes we uploaded once the upload is complete. + if (data.bytesTotal === data.bytesUploaded && file.size == null) { +``` + +i'd also change the `!file.size` to `file.size == null`: we care about unknown file sizes here, not 0-sized files, best to be explicit about it.",2021-02-24 13:06:32 +242,"@@ -98,6 +99,10 @@ module.exports = class Instagram extends Plugin { + } + + getItemName (item) { ++ if (item && item['created_time']) { ++ let date = new Date(item['created_time'] * 1000).toUTCString() ++ return `Instagram ${date}` ++ }","yes, it's nice. I'm not sure why I didn't add it earlier. @arturi ",2018-03-16 12:46:55 +716,"@@ -98,7 +98,7 @@ This takes your `server` instance and your Uppy [Options](#Options) as parameter + + ### Running as a standalone server + +-> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configure-Standalone) for the variables required. ++> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#configuring-a-standalone-server) for the variables required. + ","```suggestion +> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configuring-a-standalone-server) for the variables required. +```",2020-03-26 15:46:15 +717,"@@ -98,8 +98,8 @@ This takes your `server` instance and your Uppy [Options](#Options) as parameter + + ### Running as a standalone server + +-> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configure-Standalone) for the variables required. +- ++> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#configuring-a-standalone-server) for the variables required.","```suggestion +> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configuring-a-standalone-server) for the variables required. +```",2020-03-26 15:50:43 +718,"@@ -98,8 +98,8 @@ This takes your `server` instance and your Uppy [Options](#Options) as parameter + + ### Running as a standalone server + +-> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configure-Standalone) for the variables required. +- ++> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#configuring-a-standalone-server) for the variables required. ++> Please ensure that the required environment variables are set before running/using Companion as a standalone server. See [Configure Standalone](#Configuring-a-standalone-server) for the variables required.","```suggestion +```",2020-03-26 15:50:54 +155,"@@ -987,7 +956,7 @@ class Uppy { + createUpload (fileIDs) {",i think `createUpload` and `removeUpload` should also be private,2017-12-09 16:07:42 +195,"@@ -99,6 +99,7 @@ + ""webdriverio"": ""^4.10.1"" + }, + ""dependencies"": { ++ ""@xkeshi/image-compressor"": ""^0.5.3"",","the latest is `1.0.0`, not `0.5.3` 😉 ",2018-01-25 13:28:51 +138,"@@ -99,7 +99,7 @@ module.exports = function fileItem (props) { + } + +
    +- ${file.data.size && html`
    ${prettyBytes(file.data.size)}
    `} ++ ${isNaN(file.data.size) ? '' : html`
    ${prettyBytes(file.data.size)}
    `}","We are trying to support IE 10-11, so we’ll need a polyfill for this one, I think.",2017-11-13 18:12:45 +609,"@@ -99,9 +99,9 @@ module.exports = class Tus extends Plugin { + * + * @param {string} fileID + */ +- resetUploaderReferences (fileID) { ++ resetUploaderReferences (fileID, shouldTerminate) {","In the S3 plugin I used an options object `{ abort: true }` for this: + +https://github.com/transloadit/uppy/blob/84c3eda830bb4cd07e6ae8da2f9f53ffcc07ff3b/packages/%40uppy/aws-s3-multipart/src/index.js#L56-L60 + +might be good to do the same here for consistency reasons?",2019-10-23 11:43:57 diff --git a/docs/conclusion.md b/docs/conclusion.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/intro.md b/docs/intro.md index ffceae9..1e5919d 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -7,5 +7,12 @@ It does not go in-depth into any particular topic - check out [the Jupyter Book Check out the content pages bundled with this sample book to see more. +## Table of Contents + ```{tableofcontents} ``` + +## Bibliography + +```{bibliography} +``` diff --git a/notebooks/1_collect_reviews.ipynb b/notebooks/1_collect_reviews.ipynb new file mode 100644 index 0000000..ee0f08e --- /dev/null +++ b/notebooks/1_collect_reviews.ipynb @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Collecting Code Review Data\n", + "\n", + "In this notebook, we will collect code review data from Github. We will use the [PyGithub](https://github.com/PyGithub/PyGithub) library to interact with the Github API." + ], + "metadata": { + "collapsed": false + }, + "id": "5ef1eea9072c468d" + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "initial_id", + "metadata": { + "collapsed": true, + "ExecuteTime": { + "end_time": "2023-09-13T21:16:51.561272700Z", + "start_time": "2023-09-13T21:16:50.880313100Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\akovr\\AppData\\Local\\Temp\\ipykernel_17448\\323726258.py:5: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n", + " from tqdm.autonotebook import tqdm\n" + ] + } + ], + "source": [ + "from getpass import getpass\n", + "\n", + "from github import Auth, Github\n", + "import pandas as pd\n", + "from tqdm.autonotebook import tqdm" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Although, we can use the Github API without authentication, we will need to authenticate to increase the rate limit. We can authenticate using a [Github Access Token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token). You can then enter the token below. If you do not enter a token, the code will run without authentication, but you will be rate limited to 60 requests per hour. " + ], + "metadata": { + "collapsed": false + }, + "id": "72f54dfff3ab324a" + }, + { + "cell_type": "code", + "execution_count": 2, + "outputs": [], + "source": [ + "token = getpass(\"Enter your Github Access Token: \")\n", + "if token:\n", + " # using token\n", + " g = Github(auth=Auth.Token(token))\n", + "else:\n", + " # no token\n", + " # warn: possibly rate limited\n", + " g = Github()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-09-13T21:16:58.651064100Z", + "start_time": "2023-09-13T21:16:51.561272700Z" + } + }, + "id": "87d1643cf1710bab" + }, + { + "cell_type": "markdown", + "source": [ + "Next, we will define a function to collect code review data from a Github repository." + ], + "metadata": { + "collapsed": false + }, + "id": "9a59e87456812d86" + }, + { + "cell_type": "code", + "execution_count": 3, + "outputs": [], + "source": [ + "def collect_reviews(repo_name: str, num_comments: int = 1000, skip_author=True, allow_threads=False, save=True):\n", + " \"\"\"\n", + " Crawl a repo for code review data\n", + " :param repo_name: Repo name in format \"owner/repo\"\n", + " :param num_comments: Number of comments to load\n", + " :param skip_author: Skip comments made by the author of the pull request\n", + " :param allow_threads: Allow comments that are replies to other comments\n", + " :param save: Save the data to a csv file\n", + " :return: Returns a pandas dataframe with columns diff_hunk, human_review, created_at\n", + " \"\"\"\n", + " data = []\n", + " # diff hunk for counting\n", + " hunks = set()\n", + " # load repo\n", + " repo = g.get_repo(repo_name)\n", + " # load comments\n", + " comment_pages = repo.get_pulls_review_comments()\n", + " # iterate over comments\n", + " progress_bar = tqdm(total=num_comments)\n", + " for comment in comment_pages:\n", + " if len(hunks) >= num_comments:\n", + " # if we have enough comments, stop\n", + " break\n", + " if comment.diff_hunk in hunks:\n", + " # if we already have this diff hunk, skip\n", + " continue\n", + " # get commit author\n", + " commit_author = repo.get_git_commit(comment.commit_id).author\n", + " if skip_author and comment.user == commit_author:\n", + " # if the comment is made by the author of the pull request, skip\n", + " continue\n", + " # add comment to data, along with diff hunk, created_at and ground truth review\n", + " data.append({'diff_hunk': comment.diff_hunk, 'human_review': comment.body, 'created_at': comment.created_at})\n", + " # add diff hunk to set for counting\n", + " progress_bar.update(1)\n", + " hunks.add(comment.diff_hunk)\n", + " df = pd.DataFrame(data)\n", + " if not allow_threads:\n", + " # remove comments that are replies to other comments, keeping the first comment\n", + " df = df.loc[df.groupby('diff_hunk').created_at.idxmin()]\n", + " if save:\n", + " df.to_csv(f'../data/{repo_name.replace(\"/\", \"_\")}_{len(df)}.csv')\n", + " return df" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-09-13T21:16:58.680037100Z", + "start_time": "2023-09-13T21:16:58.601487200Z" + } + }, + "id": "b7df1e499a6c792b" + }, + { + "cell_type": "markdown", + "source": [ + "Finally, we will collect code review data from the following repositories:\n", + "- [microsoft/vscode](https://github.com/microsoft/vscode)\n", + "- [JetBrains/kotlin](https://github.com/JetBrains/kotlin)\n", + "- [transloadit/uppy](https://github.com/transloadit/uppy)\n", + "\n", + "I have chosen these repositories because they are popular, and they have a large number of pull requests with code review comments. The authors of {cite}`li2022codereviewer` have also used similar criteria to select repositories for their study.\n", + "\n", + "The data will be saved to the `data` folder." + ], + "metadata": { + "collapsed": false + }, + "id": "7c68b31943a86a32" + }, + { + "cell_type": "code", + "execution_count": 8, + "outputs": [], + "source": [ + "repos = ['microsoft/vscode', 'JetBrains/kotlin', 'transloadit/uppy']" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-09-13T21:24:48.605227900Z", + "start_time": "2023-09-13T21:24:48.598220Z" + } + }, + "id": "dc6a0070723b6860" + }, + { + "cell_type": "code", + "execution_count": 9, + "outputs": [ + { + "data": { + "text/plain": " 0%| | 0/1000 [00:00