Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d5a3732
Fix: error Sometimes ranges fail to compile properly...
sergioalcaraz May 5, 2024
c7fe314
point to 2.7 coffeescript compiler
sergioalcaraz Apr 22, 2026
1e3864f
Add Document Symbols support
sergioalcaraz Apr 22, 2026
f331295
Use CoffeeScript AST for Document Symbols
sergioalcaraz Apr 22, 2026
31f652b
Extract CoffeeScript AST parsing into coffeeAstService
sergioalcaraz Apr 22, 2026
69d3b0f
Add document symbol tests
sergioalcaraz Apr 22, 2026
1a7f7f3
Improve CoffeeScript AST -> DocumentSymbol mapping
sergioalcaraz Apr 22, 2026
999c474
Instrument coffeeAstService with debug logs
sergioalcaraz Apr 22, 2026
4387881
Add temporary console debug logs to coffeeAstService
sergioalcaraz Apr 22, 2026
dda6768
Filter document symbols to declarations only
sergioalcaraz Apr 22, 2026
a0e08e6
Include javascript mode changes for document-symbols
sergioalcaraz Apr 22, 2026
fd83810
Include object-literal and class-property symbols; skip primitive lit…
sergioalcaraz Apr 22, 2026
06f6ab6
Merge assignment-based symbols: prefer single symbol for lhs when RHS…
sergioalcaraz Apr 23, 2026
7e1ae12
Sync VS Code outline settings to server; sort DocumentSymbols by posi…
sergioalcaraz Apr 23, 2026
47430df
document-symbols: include ES6 import declarations in outline\n\nAdd s…
sergioalcaraz Apr 23, 2026
a516fdc
Added support for Document Symbols (outline)
sergioalcaraz Apr 23, 2026
9f89778
document-symbols: include CommonJS exports (module.exports, exports.*…
sergioalcaraz Apr 23, 2026
6a613ce
document-symbols: finalize export handling and member-name heuristics…
sergioalcaraz Apr 23, 2026
9ef0873
document-symbols: add export handling for ES modules\n\nEnsure 'expor…
sergioalcaraz Apr 23, 2026
f582393
document-symbols: show anonymous exported classes/functions/objects a…
sergioalcaraz Apr 23, 2026
c97a102
document-symbols: allow exported anonymous declarations to keep inner…
sergioalcaraz Apr 23, 2026
29679d4
test(document-symbols): add export-default fixtures and tests for ano…
sergioalcaraz Apr 23, 2026
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ You can **install the extension in VSCode from [HERE](https://marketplace.visual
- [x] **Hover information**
- [x] **Signature type hints** Trigger characters are both `(` and ` ` (space)
- [x] **Document highlight**
- [ ] *missing* Document symbols ("Outline"): Removed again, as they mainly led to problems. If you want symbols, additionally install [Yorkxin's extension](https://github.com/yorkxin/vscode-coffeescript-support). It's marked as deprecated but can provide this feature well.
- [x] Document symbols ("Outline")
- [x] **Find definition**
- [x] **Find references**
- **Code actions**: Organize imports only. Probably only rarely works as you intend it to. Auto imports: Not implemented as code actions, but works while autocompleting.
Expand Down
3 changes: 2 additions & 1 deletion client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export function initializeLanguageClient(lspModulePath: string): LanguageClient
const clientOptions: LanguageClientOptions = {
documentSelector,
synchronize: {
configurationSection: ['coffeesense', 'javascript', 'typescript', 'files.associations'],
// Also sync VS Code outline settings so the server can sort DocumentSymbols accordingly
configurationSection: ['coffeesense', 'javascript', 'typescript', 'files.associations', 'outline'],
fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.js,**/*.ts,**/*.json}', false, false, true)
},
initializationOptions: {
Expand Down
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"homepage": "https://github.com/phil294/coffeesense/tree/master/server",
"dependencies": {
"coffeescript": "github:edemaine/coffeescript#var-assign",
"coffeescript": "github:sergioalcaraz/coffeescript#var-assign",
"jshashes": "^1.0.8",
"typescript": "^5.1.6",
"volatile-map": "^2.0.0",
Expand Down
4 changes: 3 additions & 1 deletion server/src/embeddedSupport/languageModes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
Position,
CodeActionContext,
CodeAction,
TextDocumentEdit
TextDocumentEdit,
DocumentSymbol
} from 'vscode-languageserver-types';
import type { TextDocument } from 'vscode-languageserver-textdocument';

Expand Down Expand Up @@ -50,6 +51,7 @@ export interface LanguageMode {
findDocumentHighlight?(document: TextDocument, position: Position): DocumentHighlight[];
findDefinition?(document: TextDocument, position: Position): Definition;
findReferences?(document: TextDocument, position: Position): Location[];
findDocumentSymbols?(document: TextDocument): DocumentSymbol[];

onDocumentChanged?(filePath: string): void;
onDocumentRemoved(document: TextDocument): void;
Expand Down
69 changes: 68 additions & 1 deletion server/src/modes/script/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
CodeAction, CodeActionContext, CodeActionKind, CompletionItem, CompletionItemKind, CompletionItemTag, CompletionList, Definition, Diagnostic,
DiagnosticSeverity, DiagnosticTag, DocumentHighlight,
DocumentHighlightKind, Hover, Location, MarkedString, MarkupContent, ParameterInformation, Position, Range, SignatureHelp,
SignatureInformation, TextEdit
SignatureInformation, TextEdit, DocumentSymbol, SymbolKind
} from 'vscode-languageserver-types';
import { URI } from 'vscode-uri';
import { CoffeescriptDocumentRegions, LanguageId } from '../../embeddedSupport/embeddedSupport';
Expand All @@ -15,6 +15,7 @@ import { DependencyService, RuntimeLibrary } from '../../services/dependencyServ
import { DocumentService } from '../../services/documentService';
import { EnvironmentService } from '../../services/EnvironmentService';
import transpile_service, { common_js_variable_name_character, get_line_at_line_no, get_word_around_position, pseudo_compile_coffee } from '../../services/transpileService';
import { getDocumentSymbolsFromCoffee } from '../../services/coffeeAstService';
import { IServiceHost } from '../../services/typescriptService/serviceHost';
import { toCompletionItemKind } from '../../services/typescriptService/util';
import { CodeActionData, CodeActionDataKind, OrganizeImportsActionData } from '../../types';
Expand All @@ -23,6 +24,7 @@ import { getFileFsPath, getFilePath } from '../../utils/paths';
import { NULL_SIGNATURE } from '../nullMode';
import * as Previewer from './previewer';
import { HighlightSpanKind } from 'typescript';
import { logger } from '../../log';



Expand Down Expand Up @@ -896,9 +898,74 @@ export async function getJavascriptMode(
delete action.data;
return action;
},
findDocumentSymbols(coffee_doc: TextDocument): DocumentSymbol[] {
try {
const symbols = getDocumentSymbolsFromCoffee(coffee_doc);
if (symbols && symbols.length) return symbols;
} catch (e: any) {
logger.logDebug('coffeeAstService failed: ' + (e && e.message));
}

// Fallback: TypeScript navigation + source maps (existing logic)
const transpilation = transpile_service.result_by_uri.get(coffee_doc.uri)
const { scriptDoc: js_doc, service } = updateCurrentCoffeescriptTextDocument(coffee_doc);
if (!languageServiceIncludesFile(service, coffee_doc.uri)) {
return [];
}
const fileFsPath = getFileFsPath(js_doc.uri);
const nav = service.getNavigationTree(fileFsPath);
if (!nav || !nav.childItems) return [];
const mapKind = (k: string) => {
switch ((k || '').toLowerCase()) {
case 'module': return SymbolKind.Module;
case 'class': return SymbolKind.Class;
case 'method': return SymbolKind.Method;
case 'function': return SymbolKind.Function;
case 'constructor': return SymbolKind.Constructor;
case 'property': return SymbolKind.Property;
case 'var':
case 'local':
case 'const':
case 'let':
return SymbolKind.Variable;
case 'interface': return SymbolKind.Interface;
case 'enum': return SymbolKind.Enum;
default: return SymbolKind.Object;
}
};
const convertNode = (node: any): DocumentSymbol | null => {
const span = (node.spans && node.spans.length) ? node.spans[0] : node.textSpan || node.nameSpan;
if (!span) return null;
let range = convertRange(js_doc, span);
let selectionRange = range;
if (node.nameSpan) selectionRange = convertRange(js_doc, node.nameSpan);
if (transpilation?.source_map) {
const coffee_range = transpile_service.range_js_to_coffee(transpilation, range, coffee_doc);
const coffee_selection = transpile_service.range_js_to_coffee(transpilation, selectionRange, coffee_doc);
if (coffee_range) range = coffee_range;
if (coffee_selection) selectionRange = coffee_selection;
else if (coffee_range) selectionRange = range;
} else {
return null;
}
const children = (node.childItems || []).map((c: any) => convertNode(c)).filter((c: any) => c) as DocumentSymbol[];
return {
name: node.text || node.kind || '',
detail: '',
kind: mapKind(node.kind),
range,
selectionRange,
children: children.length ? children : undefined
} as DocumentSymbol;
};
const symbols = (nav.childItems || []).map((c: any) => convertNode(c)).filter((s: any) => s) as DocumentSymbol[];
return symbols;
},

onDocumentRemoved(document: TextDocument) {
jsDocuments.onDocumentRemoved(document);
},

onDocumentChanged(filePath: string) {
serviceHost.updateExternalDocument(filePath);
},
Expand Down
Loading