@@ -7,6 +7,14 @@ import org.javacs.kt.index.SymbolIndex
77import  org.javacs.kt.position.offset 
88import  org.javacs.kt.position.position 
99import  org.javacs.kt.util.toPath 
10+ import  org.javacs.kt.overridemembers.createFunctionStub 
11+ import  org.javacs.kt.overridemembers.createVariableStub 
12+ import  org.javacs.kt.overridemembers.getClassDescriptor 
13+ import  org.javacs.kt.overridemembers.getDeclarationPadding 
14+ import  org.javacs.kt.overridemembers.getNewMembersStartPosition 
15+ import  org.javacs.kt.overridemembers.getSuperClassTypeProjections 
16+ import  org.javacs.kt.overridemembers.hasNoBody 
17+ import  org.javacs.kt.overridemembers.overridesDeclaration 
1018import  org.jetbrains.kotlin.descriptors.ClassDescriptor 
1119import  org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor 
1220import  org.jetbrains.kotlin.descriptors.DeclarationDescriptor 
@@ -32,8 +40,6 @@ import org.jetbrains.kotlin.types.KotlinType
3240import  org.jetbrains.kotlin.types.TypeProjection 
3341import  org.jetbrains.kotlin.types.typeUtil.asTypeProjection 
3442
35- private  const  val  DEFAULT_TAB_SIZE  =  4 
36- 
3743class  ImplementAbstractMembersQuickFix  : QuickFix  {
3844    override  fun  compute (file :  CompiledFile , index :  SymbolIndex , range :  Range , diagnostics :  List <Diagnostic >): List <Either <Command , CodeAction >> {
3945        val  diagnostic =  findDiagnosticMatch(diagnostics, range)
@@ -108,127 +114,3 @@ private fun getAbstractMembersStubs(file: CompiledFile, kotlinClass: KtClass) =
108114            null 
109115        }
110116    }.flatten()
111- 
112- //  interfaces are ClassDescriptors by default. When calling AbstractClass super methods, we get a ClassConstructorDescriptor    
113- private  fun  getClassDescriptor (descriptor :  DeclarationDescriptor ? ): ClassDescriptor ?  =  if  (descriptor is  ClassDescriptor ) {
114-     descriptor
115- } else  if  (descriptor is  ClassConstructorDescriptor ) {
116-     descriptor.containingDeclaration
117- } else  {
118-     null 
119- }
120- 
121- private  fun  getSuperClassTypeProjections (file :  CompiledFile , superType :  KtSuperTypeListEntry ): List <TypeProjection > =  superType.typeReference?.typeElement?.children?.filter {
122-     it is  KtTypeArgumentList 
123- }?.flatMap {
124-     (it as  KtTypeArgumentList ).arguments
125- }?.mapNotNull {
126-     (file.referenceExpressionAtPoint(it?.startOffset ? :  0 )?.second as ?  ClassDescriptor )?.defaultType?.asTypeProjection()
127- } ? :  emptyList()
128- 
129- //  Checks if the class overrides the given declaration
130- private  fun  overridesDeclaration (kotlinClass :  KtClass , descriptor :  FunctionDescriptor ): Boolean  = 
131-     kotlinClass.declarations.any {
132-         if  (it.name ==  descriptor.name.asString() &&  it.hasModifier(KtTokens .OVERRIDE_KEYWORD )) {
133-             if  (it is  KtNamedFunction ) {
134-                 parametersMatch(it, descriptor)
135-             } else  {
136-                 true 
137-             }
138-         } else  {
139-             false 
140-         }
141-     }
142- 
143- private  fun  overridesDeclaration (kotlinClass :  KtClass , descriptor :  PropertyDescriptor ): Boolean  = 
144-     kotlinClass.declarations.any {
145-         it.name ==  descriptor.name.asString() &&  it.hasModifier(KtTokens .OVERRIDE_KEYWORD )
146-     }
147- 
148- //  Checks if two functions have matching parameters
149- private  fun  parametersMatch (function :  KtNamedFunction , functionDescriptor :  FunctionDescriptor ): Boolean  {
150-     if  (function.valueParameters.size ==  functionDescriptor.valueParameters.size) {
151-         for  (index in  0  until function.valueParameters.size) {
152-             if  (function.valueParameters[index].name !=  functionDescriptor.valueParameters[index].name.asString()) {
153-                 return  false 
154-             } else  if  (function.valueParameters[index].typeReference?.typeName() !=  functionDescriptor.valueParameters[index].type.unwrappedType().toString()) {
155-                 //  Note: Since we treat Java overrides as non nullable by default, the above test will fail when the user has made the type nullable.
156-                 //  TODO: look into this
157-                 return  false 
158-             }
159-         }
160- 
161-         if  (function.typeParameters.size ==  functionDescriptor.typeParameters.size) {
162-             for  (index in  0  until function.typeParameters.size) {
163-                 if  (function.typeParameters[index].variance !=  functionDescriptor.typeParameters[index].variance) {
164-                     return  false 
165-                 }
166-             }
167-         }
168- 
169-         return  true 
170-     }
171- 
172-     return  false 
173- }
174- 
175- private  fun  KtTypeReference.typeName (): String?  =  this .name ? :  this .typeElement?.children?.filter {
176-     it is  KtSimpleNameExpression 
177- }?.map {
178-     (it as  KtSimpleNameExpression ).getReferencedName()
179- }?.firstOrNull()
180- 
181- private  fun  createFunctionStub (function :  FunctionDescriptor ): String  {
182-     val  name =  function.name
183-     val  arguments =  function.valueParameters.map { argument -> 
184-         val  argumentName =  argument.name
185-         val  argumentType =  argument.type.unwrappedType()
186-                     
187-         " $argumentName : $argumentType " 
188-     }.joinToString(" , " 
189-     val  returnType =  function.returnType?.unwrappedType()?.toString()?.takeIf  { " Unit" !=  it }
190-     
191-     return  " override fun $name ($arguments )${returnType?.let  { " : $it " ? :  " "   { }" 
192- }
193- 
194- private  fun  createVariableStub (variable :  PropertyDescriptor ): String  {
195-     val  variableType =  variable.returnType?.unwrappedType()?.toString()?.takeIf  { " Unit" !=  it }
196-     return  " override val ${variable.name}${variableType?.let  { " : $it " ? :  " "   = TODO(\" SET VALUE\" )" 
197- }
198- 
199- //  about types: regular Kotlin types are marked T or T?, but types from Java are (T..T?) because nullability cannot be decided.
200- //  Therefore we have to unpack in case we have the Java type. Fortunately, the Java types are not marked nullable, so we default to non nullable types. Let the user decide if they want nullable types instead. With this implementation Kotlin types also keeps their nullability
201- private  fun  KotlinType.unwrappedType (): KotlinType  =  this .unwrap().makeNullableAsSpecified(this .isMarkedNullable)
202- 
203- private  fun  getDeclarationPadding (file :  CompiledFile , kotlinClass :  KtClass ): String  {
204-     //  If the class is not empty, the amount of padding is the same as the one in the last declaration of the class
205-     val  paddingSize =  if  (kotlinClass.declarations.isNotEmpty()) {
206-         val  lastFunctionStartOffset =  kotlinClass.declarations.last().startOffset
207-         position(file.content, lastFunctionStartOffset).character
208-     } else  {
209-         //  Otherwise, we just use a default tab size in addition to any existing padding
210-         //  on the class itself (note that the class could be inside another class, for example)
211-         position(file.content, kotlinClass.startOffset).character +  DEFAULT_TAB_SIZE 
212-     }
213- 
214-     return  "  " 
215- }
216- 
217- private  fun  getNewMembersStartPosition (file :  CompiledFile , kotlinClass :  KtClass ): Position ?  = 
218-     //  If the class is not empty, the new member will be put right after the last declaration
219-     if  (kotlinClass.declarations.isNotEmpty()) {
220-         val  lastFunctionEndOffset =  kotlinClass.declarations.last().endOffset
221-         position(file.content, lastFunctionEndOffset)
222-     } else  { //  Otherwise, the member is put at the beginning of the class
223-         val  body =  kotlinClass.body
224-         if  (body !=  null ) {
225-             position(file.content, body.startOffset +  1 )
226-         } else  {
227-             //  function has no body. We have to create one. New position is right after entire kotlin class text (with space)
228-             val  newPosCorrectLine =  position(file.content, kotlinClass.startOffset +  1 )
229-             newPosCorrectLine.character =  (kotlinClass.text.length +  2 )
230-             newPosCorrectLine
231-         }
232-     }
233- 
234- private  fun  KtClass.hasNoBody () =  null  ==  this .body
0 commit comments