Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,30 @@ public void createControl(Composite parent)

projectCombo = new Combo(comp, SWT.NONE);
projectCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Optional<IProject> optProject = Optional.ofNullable(EclipseUtil.getSelectedIDFProjectInExplorer());

// Safely get selected IDF project with error handling
IProject selectedProject = null;
try {
selectedProject = EclipseUtil.getSelectedIDFProjectInExplorer();
} catch (NoSuchMethodError e) {
// Fallback: try to get any selected project
try {
selectedProject = EclipseUtil.getSelectedProjectInExplorer();
if (selectedProject != null) {
try {
if (!selectedProject.hasNature(IDFProjectNature.ID)) {
selectedProject = null; // Not an IDF project
}
} catch (CoreException ce) {
selectedProject = null;
}
}
} catch (Exception ex) {
// If all else fails, selectedProject remains null
}
}

Optional<IProject> optProject = Optional.ofNullable(selectedProject);
optProject.ifPresent(project -> projectCombo.setText(project.getName()));
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (IProject project : projects)
Expand Down
8 changes: 7 additions & 1 deletion bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.cdt.cmake.ui,
org.eclipse.swt;visibility:=reexport,
org.eclipse.ui;visibility:=reexport,
org.eclipse.ui.workbench,
org.eclipse.jface,
org.eclipse.cdt.core.native,
org.eclipse.cdt.core;bundle-version="9.0.0",
Expand All @@ -33,6 +34,9 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.nebula.widgets.xviewer;bundle-version="1.1.0",
org.eclipse.nebula.widgets.xviewer.core;bundle-version="1.0.0",
org.eclipse.text,
org.eclipse.jface.text,
org.eclipse.ui.genericeditor,
org.eclipse.ui.editors,
org.eclipse.cdt.native.serial,
org.eclipse.ui.workbench.texteditor,
org.eclipse.ui.intro,
Expand All @@ -45,7 +49,9 @@ Require-Bundle: org.eclipse.core.runtime,
org.freemarker.freemarker,
org.eclipse.tools.templates.freemarker,
org.eclipse.cdt.lsp;bundle-version="3.0.0",
org.eclipse.cdt.lsp.clangd;bundle-version="3.0.0"
org.eclipse.cdt.lsp.clangd;bundle-version="3.0.0",
org.eclipse.tm4e.registry,
org.eclipse.tm4e.languageconfiguration
Automatic-Module-Name: com.espressif.idf.ui
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
Expand Down
4 changes: 3 additions & 1 deletion bundles/com.espressif.idf.ui/build.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ bin.includes = META-INF/,\
index.html,\
go.css,\
lib/commonmark-0.24.0.jar,\
lib/jfreechart-1.5.5.jar
lib/jfreechart-1.5.5.jar,\
syntaxes/,\
kconfig-language-configuration.json

29 changes: 29 additions & 0 deletions bundles/com.espressif.idf.ui/kconfig-language-configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"comments": {
"lineComment": "#"
},
"brackets": [
["(", ")"],
["menu", "endmenu"],
["choice", "endchoice"]
],
"autoClosingPairs": [
["(", ")"],
["\"", "\""]
],
"surroundingPairs": [
["(", ")"],
["\"", "\""]
],
"indentationRules": {
"increaseIndentPattern": "^([\\s]*)(menu|config|menuconfig|choice|help|comment)(.*)$",
"decreaseIndentPattern": "^(endmenu|endchoice|endif)(.*)$"
},
"wordPattern": "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b",
"folding": {
"markers": {
"start": "^\\s*#\\s*region\\b",
"end": "^\\s*#\\s*endregion\\b"
}
}
}
53 changes: 53 additions & 0 deletions bundles/com.espressif.idf.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,16 @@
id="com.espressif.idf.ui.editor.idfsize"
name="%editor.name">
</editor>
<editor
class="com.espressif.idf.ui.kconfig.KConfigEditor"
contributorClass="org.eclipse.ui.editors.text.TextEditorActionContributor"
default="true"
id="com.espressif.idf.ui.editor.kconfig"
name="KConfig Editor">
<contentTypeBinding
contentTypeId="com.espressif.idf.ui.kconfig.contentType">
</contentTypeBinding>
</editor>
</extension>
<extension
point="org.eclipse.cdt.launch.coreBuildTab">
Expand Down Expand Up @@ -845,6 +855,44 @@
name="Partition Table"
priority="normal">
</content-type>
<content-type
base-type="org.eclipse.core.runtime.text"
file-patterns="Kconfig,Kconfig.projbuild,Kconfig.in"
id="com.espressif.idf.ui.kconfig.contentType"
name="KConfig"
priority="normal">
</content-type>
<file-association
content-type="com.espressif.idf.ui.kconfig.contentType"
file-extensions="Kconfig,Kconfig.projbuild,Kconfig.in">
</file-association>
Comment on lines +865 to +868
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix file-extensions attribute: should contain only extension names, not full filename patterns.

The file-extensions attribute on line 867 contains full filename patterns ("Kconfig", "Kconfig.projbuild", "Kconfig.in"), but this attribute expects only extension names without dots or path separators. The file-patterns attribute on line 860 already correctly specifies these filenames.

Remove the redundant file-association block (lines 865–868), as the content-type's file-patterns already establishes the file matching.

- <file-association
-       content-type="com.espressif.idf.ui.kconfig.contentType"
-       file-extensions="Kconfig,Kconfig.projbuild,Kconfig.in">
- </file-association>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<file-association
content-type="com.espressif.idf.ui.kconfig.contentType"
file-extensions="Kconfig,Kconfig.projbuild,Kconfig.in">
</file-association>
🤖 Prompt for AI Agents
In bundles/com.espressif.idf.ui/plugin.xml around lines 865 to 868, the
file-association block uses the file-extensions attribute incorrectly by listing
full filename patterns; since file-patterns already covers these names, remove
the redundant file-association block (lines 865–868) entirely so only the
existing file-patterns entry defines the mappings.

</extension>
<extension
point="org.eclipse.tm4e.registry.grammars">
<grammar
contentTypeId="com.espressif.idf.ui.kconfig.contentType"
path="syntaxes/kconfig.tmLanguage.json"
scopeName="source.kconfig">
</grammar>
<scopeNameContentTypeBinding
contentTypeId="com.espressif.idf.ui.kconfig.contentType"
scopeName="source.kconfig">
</scopeNameContentTypeBinding>
</extension>
<extension
point="org.eclipse.tm4e.languageconfiguration.languageConfigurations">
<languageConfiguration
contentTypeId="com.espressif.idf.ui.kconfig.contentType"
path="kconfig-language-configuration.json">
</languageConfiguration>
</extension>
<extension
point="org.eclipse.ui.genericeditor.contentAssistProcessors">
<contentAssistProcessor
class="com.espressif.idf.ui.kconfig.KConfigContentAssistProcessor"
contentType="com.espressif.idf.ui.kconfig.contentType"
triggerCharacters=" ">
</contentAssistProcessor>
</extension>
<extension
point="org.eclipse.ltk.core.refactoring.renameParticipants">
Expand All @@ -865,5 +913,10 @@
id="com.espressif.idf.ui.espLaunchScope"
name="Espressif Launch Scope">
</context>
<context
id="com.espressif.idf.ui.kconfig.editorContext"
name="KConfig Editor Context"
parentId="org.eclipse.ui.textEditorScope">
</context>
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*******************************************************************************
* Copyright 2024 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
* Use is subject to license terms.
*******************************************************************************/
package com.espressif.idf.ui.kconfig;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;

/**
* @author Kondal Kolipaka <kondal.kolipaka@espressif.com>
*/
public class KConfigContentAssistProcessor implements IContentAssistProcessor
{
private static final String[] MAIN_KEYWORDS = {
"config", "menuconfig", "choice", "endchoice", "menu", "endmenu",
"if", "endif", "source", "comment", "mainmenu"
};

private static final String[] TYPES = {
"bool", "tristate", "int", "hex", "string"
};

private static final String[] PROPERTIES = {
"default", "depends", "select", "imply", "range", "help", "prompt",
"visible", "optional"
};

private static final String[] VALUES = {
"y", "n", "m"
};

Comment on lines +21 to +38
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about having it in a separate interface or enum. Seems like these values can even be in an enum to avoid any NLS tags as well since they seem to be pretty consistent

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enums or interfaces are useful if you plan to reuse them elsewhere. Since these keywords are only used within the content assist processor, I don't think they're a good fit here

@coderabbitai what do you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kolipakakondal I think your approach is reasonable here. The string arrays are simple, clear, and work well for the content assist processor. Since the logic is straightforward prefix matching and these constants aren't currently shared across multiple classes, keeping them colocated is pragmatic.

One minor consideration: the kconfig.tmLanguage.json file also defines similar keywords for syntax highlighting. If you find yourself needing to keep these in sync across multiple files in the future, that might be a signal to centralize them. But for now, the current implementation is clean and maintainable.

The main benefit of enums would be type safety, but since you're doing string prefix matching anyway, it would just add conversion overhead without much practical gain in this specific use case.

@Override
public ICompletionProposal[] computeCompletionProposals(org.eclipse.jface.text.ITextViewer viewer, int offset)
{
List<ICompletionProposal> proposals = new ArrayList<>();

String text = viewer.getDocument().get();
int lineStart = text.lastIndexOf('\n', offset - 1) + 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System.lineSeparator() seems like a safe way to avoid using '\n' directly

String lineText = text.substring(lineStart, offset).trim();

for (String keyword : MAIN_KEYWORDS) {
if (keyword.toLowerCase().startsWith(lineText.toLowerCase())) {
proposals.add(createProposal(keyword, offset - lineText.length(), lineText.length(), keyword));
}
}

for (String type : TYPES) {
if (type.toLowerCase().startsWith(lineText.toLowerCase())) {
proposals.add(createProposal(type, offset - lineText.length(), lineText.length(), type));
}
}

for (String property : PROPERTIES) {
if (property.toLowerCase().startsWith(lineText.toLowerCase())) {
proposals.add(createProposal(property, offset - lineText.length(), lineText.length(), property));
}
}

for (String value : VALUES) {
if (value.toLowerCase().startsWith(lineText.toLowerCase())) {
proposals.add(createProposal(value, offset - lineText.length(), lineText.length(), value));
}
}

return proposals.toArray(new ICompletionProposal[proposals.size()]);
}

private ICompletionProposal createProposal(String text, int offset, int length, String displayText) {
return new CompletionProposal(text, offset, length, text.length(), null, displayText, null, null);
}

@Override
public IContextInformation[] computeContextInformation(org.eclipse.jface.text.ITextViewer viewer, int offset)
{
return null;
}

@Override
public char[] getCompletionProposalAutoActivationCharacters()
{
return new char[] { ' ', '\t', '\n' };
}

@Override
public char[] getContextInformationAutoActivationCharacters()
{
return null;
}

@Override
public String getErrorMessage()
{
return null;
}

@Override
public IContextInformationValidator getContextInformationValidator()
{
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright 2024 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
* Use is subject to license terms.
*******************************************************************************/
package com.espressif.idf.ui.kconfig;

import org.eclipse.ui.internal.genericeditor.ExtensionBasedTextEditor;

/**
* @author Kondal Kolipaka <kondal.kolipaka@espressif.com>
*/
@SuppressWarnings("restriction")
public class KConfigEditor extends ExtensionBasedTextEditor
{
public static final String KCONFIG_EDITOR_ID = "com.espressif.idf.ui.kconfig.KConfigEditor";
public static final String KCONFIG_CONTENT_TYPE = "com.espressif.idf.ui.kconfig.contentType";
private static final String CONTEXT_ID = "com.espressif.idf.ui.kconfig.editorContext";

public KConfigEditor()
{
super();
}

@Override
protected void initializeKeyBindingScopes() {
setKeyBindingScopes(new String[] { CONTEXT_ID });
}
}
Loading
Loading