Commit 37946a16 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

IDE: member and function param completion for nested classes (issue #425)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent d83be96f
......@@ -308,7 +308,7 @@ public final class Class_Type extends Type implements ITypeWithComponents {
}
/**
* Checks if the class is declared using the '@abstract' modifier
* Checks if the class is declared using the '@final' modifier
* @return
*/
public boolean isFinal() {
......
......@@ -7,6 +7,7 @@
******************************************************************************/
package org.eclipse.titan.designer.editors.ttcn3editor;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -23,17 +24,16 @@ import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;
import org.eclipse.titan.designer.Activator;
import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.ISubReference;
import org.eclipse.titan.designer.AST.IType;
import org.eclipse.titan.designer.AST.Identifier;
import org.eclipse.titan.designer.AST.Identifier.Identifier_type;
import org.eclipse.titan.designer.AST.Module;
import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.TTCN3.Expected_Value_type;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Var;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Definition;
......@@ -42,7 +42,6 @@ import org.eclipse.titan.designer.AST.TTCN3.definitions.Timer;
import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock;
import org.eclipse.titan.designer.AST.TTCN3.types.Class_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Component_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Function_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.PortTypeBody;
import org.eclipse.titan.designer.consoles.TITANDebugConsole;
import org.eclipse.titan.designer.editors.ProposalCollector;
......@@ -86,10 +85,14 @@ public final class ContentAssistProcessor implements IContentAssistProcessor {
final TTCN3ReferenceParser refParser = new TTCN3ReferenceParser(true);
final Reference functionRef = refParser.findReferenceForFunctionParamsCompletion(file, offset, doc);
final Reference classRef = refParser.findReferenceForClassMemberCompletion(file, offset, doc);
final Reference ref = refParser.findReferenceForCompletion(file, offset, doc);
Reference ref = refParser.findReferenceForClassMemberCompletion(file, offset, doc);
Reference oldRef = refParser.findReferenceForCompletion(file, offset, doc);
if (ref == null) {
ref = functionRef;
}
if (ref == null || ref.getSubreferences().isEmpty()) {
if (((ref == null || ref.getSubreferences().isEmpty()) && oldRef == null)) {
return new ICompletionProposal[] {};
}
......@@ -100,8 +103,18 @@ public final class ContentAssistProcessor implements IContentAssistProcessor {
if (tempModule != null) {
moduleName = tempModule.getName();
scope = tempModule.getSmallestEnclosingScope(refParser.getReplacementOffset());
ref.setMyScope(scope);
ref.detectModid();
if (ref != null) {
ref.setMyScope(scope);
ref.detectModid();
}
if (functionRef != null) {
functionRef.setMyScope(scope);
functionRef.detectModid();
}
if (oldRef != null) {
oldRef.setMyScope(scope);
oldRef.detectModid();
}
}
final IPreferencesService prefs = Platform.getPreferencesService();
......@@ -110,75 +123,43 @@ public final class ContentAssistProcessor implements IContentAssistProcessor {
}
final TemplateContextType contextType = new TemplateContextType(TTCN3CodeSkeletons.CONTEXT_IDENTIFIER, TTCN3CodeSkeletons.CONTEXT_NAME);
final ProposalCollector propCollector = new ProposalCollector(Identifier_type.ID_TTCN, TTCN3CodeSkeletons.CONTEXT_IDENTIFIER, contextType,
final ProposalCollector propCollector;
if (functionRef != null) {
propCollector = new ProposalCollector(Identifier_type.ID_TTCN, TTCN3CodeSkeletons.CONTEXT_IDENTIFIER, contextType,
doc, functionRef, refParser.getReplacementOffset());
} else if (ref != null) {
propCollector = new ProposalCollector(Identifier_type.ID_TTCN, TTCN3CodeSkeletons.CONTEXT_IDENTIFIER, contextType,
doc, ref, refParser.getReplacementOffset());
if (functionRef != null && scope != null) {
functionRef.setMyScope(scope);
functionRef.detectModid();
Scope fscope = scope.getAssignmentsScope();
if (fscope != null) {
Assignment assignment = fscope.getAssBySRef(tempModule.getLastCompilationTimeStamp(), functionRef);
if (assignment instanceof Def_Function) {
StyledString funcText = ((Def_Function)assignment).getStyledProposalText();
StyledCompletionProposal p = new StyledCompletionProposal("", offset, offset, offset, // FIXME : fix offsets
ImageCache.getImage(((Def_Function)assignment).getOutlineIcon()), "", null,
((Def_Function)assignment).getProposalText());
p.append(funcText);
propCollector.addProposal(p);
propCollector.markPosition();
}
}
} else {
propCollector = new ProposalCollector(Identifier_type.ID_TTCN, TTCN3CodeSkeletons.CONTEXT_IDENTIFIER, contextType,
doc, oldRef, refParser.getReplacementOffset());
}
if (classRef != null && scope != null) {
classRef.setMyScope(scope);
classRef.detectModid();
final CompilationTimeStamp timestamp = tempModule.getLastCompilationTimeStamp();
Assignment assignment = scope.getAssBySRef(timestamp, classRef);
if (assignment instanceof Def_Var) {
IType type = assignment.getType(timestamp);
if (type != null ) {
IType refd = type.getTypeRefdLast(timestamp);
if (refd instanceof Class_Type) {
Class_Type ct = (Class_Type)refd;
for (Map.Entry<String, Definition> entry : ct.getClassBody().getDefinitionMap().entrySet()) {
final Definition d = entry.getValue();
final String memberName = d.getIdentifier().getDisplayName();
if (d instanceof Def_Function) {
memberName.concat("()");
}
final IType memberType = d.getType(timestamp);
final String memberTypeName = memberType != null ? memberType.getTypename() : "";
String visibility;
Stylers.ColoredStyler styler = null;
switch (d.getVisibilityModifier()) {
case Private:
styler = new Stylers.ColoredStyler(Stylers.PrivateColor);
visibility = "private";
break;
case Public:
visibility = "public";
styler = new Stylers.ColoredStyler(Stylers.PublicColor);
break;
default:
visibility = "protected";
styler = new Stylers.ColoredStyler(Stylers.ProtectedColor);
}
final String context = "<i>" + visibility + "</i> <b>" + memberTypeName + "</b> " + memberName ;
StyledCompletionProposal scp = new StyledCompletionProposal(memberName, offset, 0, memberName.length(),
ImageCache.getImage(d.getOutlineIcon()), memberName, null, context);
scp.append(" \u25fc", styler);
propCollector.addProposal(scp);
}
propCollector.sortAll();
return propCollector.getCompletitions();
}
final CompilationTimeStamp timestamp = tempModule.getLastCompilationTimeStamp();
if (ref != null ) {
Assignment assignment = scope.getAssBySRef(timestamp, ref);
IType type = assignment.getType(timestamp);
if (type != null) {
if (ref.getSubreferences().size() > 1) {
type = type.getFieldType(timestamp, ref, 1, Expected_Value_type.EXPECTED_DYNAMIC_VALUE, null, false);
} else {
type = type.getTypeRefdLast(timestamp);
}
if (type instanceof Class_Type) {
getClassProposals(tempModule, ref, scope, propCollector, offset);
}
}
}
if (functionRef != null) {
getFunctionProposals(tempModule, functionRef, scope, propCollector, offset);
}
ref = oldRef;
propCollector.setProjectParser(projectSourceParser);
if (moduleName == null) {
// rootless behavior
......@@ -227,7 +208,7 @@ public final class ContentAssistProcessor implements IContentAssistProcessor {
}
propCollector.sortTillMarked();
propCollector.markPosition();
if (ref.getModuleIdentifier() == null) {
if (scope == null) {
TTCN3CodeSkeletons.addSkeletonProposals(doc, refParser.getReplacementOffset(), propCollector);
......@@ -305,4 +286,98 @@ public final class ContentAssistProcessor implements IContentAssistProcessor {
return null;
}
private void getClassProposals(Module module, Reference ref, Scope scope, ProposalCollector propCollector, int offset) {
if (ref != null && scope != null) {
final CompilationTimeStamp timestamp = module.getLastCompilationTimeStamp();
Assignment assignment = scope.getAssBySRef(timestamp, ref);
if (assignment instanceof Def_Var) {
IType type = assignment.getType(timestamp);
if (type != null ) {
IType refd = type.getTypeRefdLast(timestamp);
if (refd instanceof Class_Type) {
Class_Type ct = (Class_Type)refd;
final IType fieldType = ct.getFieldType(timestamp, ref, 1, Expected_Value_type.EXPECTED_DYNAMIC_VALUE, null, false);
if (fieldType instanceof Class_Type) {
ct = (Class_Type)fieldType;
for (Map.Entry<String, Definition> entry : ct.getClassBody().getDefinitionMap().entrySet()) {
final Definition d = entry.getValue();
final String memberName = d.getIdentifier().getDisplayName();
if (d instanceof Def_Function) {
memberName.concat("()");
}
final IType memberType = d.getType(timestamp);
final String memberTypeName = memberType != null ? memberType.getTypename() : "";
String visibility;
Stylers.ColoredStyler styler = null;
switch (d.getVisibilityModifier()) {
case Private:
styler = new Stylers.ColoredStyler(Stylers.PrivateColor);
visibility = "private";
break;
case Public:
visibility = "public";
styler = new Stylers.ColoredStyler(Stylers.PublicColor);
break;
default:
visibility = "protected";
styler = new Stylers.ColoredStyler(Stylers.ProtectedColor);
}
final String context = "<i>" + visibility + "</i> <b>" + memberTypeName + "</b> " + memberName ;
StyledCompletionProposal scp = new StyledCompletionProposal(memberName, offset, 0, memberName.length(),
ImageCache.getImage(d.getOutlineIcon()), memberName, null, context);
scp.append(" \u25fc", styler);
propCollector.addProposal(scp);
}
propCollector.sortAll();
}
}
}
}
}
}
private void getFunctionProposals(Module module, Reference functionRef, Scope scope, ProposalCollector propCollector, int offset) {
final CompilationTimeStamp timestamp = module.getLastCompilationTimeStamp();
if (functionRef != null && scope != null) {
Scope fscope = scope.getAssignmentsScope();
if (fscope != null) {
Assignment assignment = fscope.getAssBySRef(module.getLastCompilationTimeStamp(), functionRef);
if (assignment == null) {
List<ISubReference> sublist = functionRef.getSubreferences();
if (sublist == null)
return;
ISubReference sub = sublist.get(sublist.size() - 1);
Identifier subid = sub.getId();
functionRef.removeLastSubReference();
assignment = scope.getAssBySRef(module.getLastCompilationTimeStamp(), functionRef);
if (assignment instanceof Def_Var) {
IType type = assignment.getType(timestamp);
if (type != null ) {
IType refd = type.getTypeRefdLast(timestamp);
if (refd instanceof Class_Type) {
Class_Type ct = (Class_Type)refd;
final IType fieldType = ct.getFieldType(timestamp, functionRef, 1, Expected_Value_type.EXPECTED_DYNAMIC_VALUE, null, false);
if (fieldType instanceof Class_Type) {
Class_Type innerClass = (Class_Type)fieldType;
assignment = innerClass.getClassBody().getAssByIdentifier(timestamp, subid);
}
}
}
}
}
if (assignment instanceof Def_Function) {
StyledString funcText = ((Def_Function)assignment).getStyledProposalText();
StyledCompletionProposal p = new StyledCompletionProposal("", offset, offset, offset, // FIXME : fix offsets
ImageCache.getImage(((Def_Function)assignment).getOutlineIcon()), "", null,
((Def_Function)assignment).getProposalText());
p.append(funcText);
propCollector.addProposal(p);
propCollector.markPosition();
}
}
}
}
}
......@@ -71,7 +71,7 @@ public final class TTCN3ReferenceParser implements IReferenceParser {
while (Character.isWhitespace(document.getChar(ofs)) && ofs > 0) {
ofs--;
} ;
ofs = findIdentifierStart(ofs, document);
ofs = findClassIdentifierStart(ofs, document);
final String toBeParsed = document.get(ofs + 1, offset - ofs - 2);
reference = TTCN3ReferenceAnalyzer.parseForCompletion(file, toBeParsed);
}
......@@ -97,7 +97,7 @@ public final class TTCN3ReferenceParser implements IReferenceParser {
if (-1 == ofs) {
return reference;
}
ofs = findIdentifierStart(ofs, document);
ofs = findClassIdentifierStart(ofs, document);
final String toBeParsed = document.get(ofs + 2, offset - ofs - 3);
reference = TTCN3ReferenceAnalyzer.parseForCompletion(file, toBeParsed);
}
......@@ -126,6 +126,16 @@ public final class TTCN3ReferenceParser implements IReferenceParser {
return ofs;
}
private int findClassIdentifierStart(int oft, final IDocument document) throws BadLocationException {
char c;
do {
c = document.getChar(ofs);
ofs--;
} while ((Character.isAlphabetic(c) || Character.isDigit(c) || c == '_' || c == '.') && ofs > 0);
return ofs;
}
@Override
public Reference findReferenceForCompletion(final IFile file, final int offset, final IDocument document) {
Reference reference = null;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment