Skip to content

Commit

Permalink
fix: toString() and code style
Browse files Browse the repository at this point in the history
  • Loading branch information
balaji-sivasakthi committed Feb 22, 2024
1 parent 1adce32 commit a1a5c2e
Show file tree
Hide file tree
Showing 3 changed files with 831 additions and 842 deletions.
322 changes: 160 additions & 162 deletions src/services/cssHover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,166 +13,164 @@ import { isDefined } from '../utils/objects';
import { CSSDataManager } from '../languageFacts/dataManager';

export class CSSHover {
private supportsMarkdown: boolean | undefined;
private readonly selectorPrinting: SelectorPrinting;
private defaultSettings?: HoverSettings;

constructor(private readonly clientCapabilities: ClientCapabilities | undefined, private readonly cssDataManager: CSSDataManager) {
this.selectorPrinting = new SelectorPrinting(cssDataManager);
}

public configure(settings: HoverSettings | undefined) {
this.defaultSettings = settings;
}


public doHover(document: TextDocument, position: Position, stylesheet: nodes.Stylesheet, settings = this.defaultSettings): Hover | null {
function getRange(node: nodes.Node) {
return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
}
const offset = document.offsetAt(position);
const nodepath = nodes.getNodePath(stylesheet, offset);

/**
* nodepath is top-down
* Build up the hover by appending inner node's information
*/
let hover: Hover | null = null;
let flagOpts:{text:string;isMedia:boolean};

for (let i = 0; i < nodepath.length; i++) {
const node = nodepath[i];

if (node instanceof nodes.Media){
const regex = /@media[^\{]+/g;
const matches = node.getText().match(regex);
flagOpts = {
isMedia:true,
text:matches?.[0].toString()!
};
}

if (node instanceof nodes.Selector) {
hover = {
contents: this.selectorPrinting.selectorToMarkedString(<nodes.Selector>node, flagOpts!),
range: getRange(node)
};
break;
}

if (node instanceof nodes.SimpleSelector) {
/**
* Some sass specific at rules such as `@at-root` are parsed as `SimpleSelector`
*/
if (!startsWith(node.getText(), '@')) {
hover = {
contents: this.selectorPrinting.simpleSelectorToMarkedString(<nodes.SimpleSelector>node),
range: getRange(node)
};
}
break;
}

if (node instanceof nodes.Declaration) {
const propertyName = node.getFullPropertyName();
const entry = this.cssDataManager.getProperty(propertyName);
if (entry) {
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
if (contents) {
hover = {
contents,
range: getRange(node)
};
} else {
hover = null;
}
}
continue;
}

if (node instanceof nodes.UnknownAtRule) {
const atRuleName = node.getText();
const entry = this.cssDataManager.getAtDirective(atRuleName);
if (entry) {
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
if (contents) {
hover = {
contents,
range: getRange(node)
};
} else {
hover = null;
}
}
continue;
}

if (node instanceof nodes.Node && node.type === nodes.NodeType.PseudoSelector) {
const selectorName = node.getText();
const entry =
selectorName.slice(0, 2) === '::'
? this.cssDataManager.getPseudoElement(selectorName)
: this.cssDataManager.getPseudoClass(selectorName);
if (entry) {
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
if (contents) {
hover = {
contents,
range: getRange(node)
};
} else {
hover = null;
}
}
continue;
}
}


if (hover) {
hover.contents = this.convertContents(hover.contents);
}

return hover;
}

private convertContents(contents: MarkupContent | MarkedString | MarkedString[]): MarkupContent | MarkedString | MarkedString[] {
if (!this.doesSupportMarkdown()) {
if (typeof contents === 'string') {
return contents;
}
// MarkupContent
else if ('kind' in contents) {
return {
kind: 'plaintext',
value: contents.value
};
}
// MarkedString[]
else if (Array.isArray(contents)) {
return contents.map(c => {
return typeof c === 'string' ? c : c.value;
});
}
// MarkedString
else {
return contents.value;
}
}

return contents;
}

private doesSupportMarkdown() {
if (!isDefined(this.supportsMarkdown)) {
if (!isDefined(this.clientCapabilities)) {
this.supportsMarkdown = true;
return this.supportsMarkdown;
}

const hover = this.clientCapabilities.textDocument && this.clientCapabilities.textDocument.hover;
this.supportsMarkdown = hover && hover.contentFormat && Array.isArray(hover.contentFormat) && hover.contentFormat.indexOf(MarkupKind.Markdown) !== -1;
}
return <boolean>this.supportsMarkdown;
}
private supportsMarkdown: boolean | undefined;
private readonly selectorPrinting: SelectorPrinting;
private defaultSettings?: HoverSettings;

constructor(
private readonly clientCapabilities: ClientCapabilities | undefined,
private readonly cssDataManager: CSSDataManager,
) {
this.selectorPrinting = new SelectorPrinting(cssDataManager);
}

public configure(settings: HoverSettings | undefined) {
this.defaultSettings = settings;
}

public doHover(document: TextDocument, position: Position, stylesheet: nodes.Stylesheet, settings = this.defaultSettings): Hover | null {
function getRange(node: nodes.Node) {
return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
}
const offset = document.offsetAt(position);
const nodepath = nodes.getNodePath(stylesheet, offset);

/**
* nodepath is top-down
* Build up the hover by appending inner node's information
*/
let hover: Hover | null = null;
let flagOpts: { text: string; isMedia: boolean };

for (let i = 0; i < nodepath.length; i++) {
const node = nodepath[i];

if (node instanceof nodes.Media) {
const regex = /@media[^\{]+/g;
const matches = node.getText().match(regex);
flagOpts = {
isMedia: true,
text: matches?.[0]!,
};
}

if (node instanceof nodes.Selector) {
hover = {
contents: this.selectorPrinting.selectorToMarkedString(<nodes.Selector>node, flagOpts!),
range: getRange(node),
};
break;
}

if (node instanceof nodes.SimpleSelector) {
/**
* Some sass specific at rules such as `@at-root` are parsed as `SimpleSelector`
*/
if (!startsWith(node.getText(), '@')) {
hover = {
contents: this.selectorPrinting.simpleSelectorToMarkedString(<nodes.SimpleSelector>node),
range: getRange(node),
};
}
break;
}

if (node instanceof nodes.Declaration) {
const propertyName = node.getFullPropertyName();
const entry = this.cssDataManager.getProperty(propertyName);
if (entry) {
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
if (contents) {
hover = {
contents,
range: getRange(node),
};
} else {
hover = null;
}
}
continue;
}

if (node instanceof nodes.UnknownAtRule) {
const atRuleName = node.getText();
const entry = this.cssDataManager.getAtDirective(atRuleName);
if (entry) {
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
if (contents) {
hover = {
contents,
range: getRange(node),
};
} else {
hover = null;
}
}
continue;
}

if (node instanceof nodes.Node && node.type === nodes.NodeType.PseudoSelector) {
const selectorName = node.getText();
const entry = selectorName.slice(0, 2) === '::' ? this.cssDataManager.getPseudoElement(selectorName) : this.cssDataManager.getPseudoClass(selectorName);
if (entry) {
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
if (contents) {
hover = {
contents,
range: getRange(node),
};
} else {
hover = null;
}
}
continue;
}
}

if (hover) {
hover.contents = this.convertContents(hover.contents);
}

return hover;
}

private convertContents(contents: MarkupContent | MarkedString | MarkedString[]): MarkupContent | MarkedString | MarkedString[] {
if (!this.doesSupportMarkdown()) {
if (typeof contents === 'string') {
return contents;
}
// MarkupContent
else if ('kind' in contents) {
return {
kind: 'plaintext',
value: contents.value,
};
}
// MarkedString[]
else if (Array.isArray(contents)) {
return contents.map((c) => {
return typeof c === 'string' ? c : c.value;
});
}
// MarkedString
else {
return contents.value;
}
}

return contents;
}

private doesSupportMarkdown() {
if (!isDefined(this.supportsMarkdown)) {
if (!isDefined(this.clientCapabilities)) {
this.supportsMarkdown = true;
return this.supportsMarkdown;
}

const hover = this.clientCapabilities.textDocument && this.clientCapabilities.textDocument.hover;
this.supportsMarkdown = hover && hover.contentFormat && Array.isArray(hover.contentFormat) && hover.contentFormat.indexOf(MarkupKind.Markdown) !== -1;
}
return <boolean>this.supportsMarkdown;
}
}
Loading

0 comments on commit a1a5c2e

Please sign in to comment.