Skip to content

Commit dfb8281

Browse files
fix: toString() and code style
1 parent 1adce32 commit dfb8281

File tree

3 files changed

+830
-842
lines changed

3 files changed

+830
-842
lines changed

src/services/cssHover.ts

Lines changed: 160 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -13,166 +13,164 @@ import { isDefined } from '../utils/objects';
1313
import { CSSDataManager } from '../languageFacts/dataManager';
1414

1515
export class CSSHover {
16-
private supportsMarkdown: boolean | undefined;
17-
private readonly selectorPrinting: SelectorPrinting;
18-
private defaultSettings?: HoverSettings;
19-
20-
constructor(private readonly clientCapabilities: ClientCapabilities | undefined, private readonly cssDataManager: CSSDataManager) {
21-
this.selectorPrinting = new SelectorPrinting(cssDataManager);
22-
}
23-
24-
public configure(settings: HoverSettings | undefined) {
25-
this.defaultSettings = settings;
26-
}
27-
28-
29-
public doHover(document: TextDocument, position: Position, stylesheet: nodes.Stylesheet, settings = this.defaultSettings): Hover | null {
30-
function getRange(node: nodes.Node) {
31-
return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
32-
}
33-
const offset = document.offsetAt(position);
34-
const nodepath = nodes.getNodePath(stylesheet, offset);
35-
36-
/**
37-
* nodepath is top-down
38-
* Build up the hover by appending inner node's information
39-
*/
40-
let hover: Hover | null = null;
41-
let flagOpts:{text:string;isMedia:boolean};
42-
43-
for (let i = 0; i < nodepath.length; i++) {
44-
const node = nodepath[i];
45-
46-
if (node instanceof nodes.Media){
47-
const regex = /@media[^\{]+/g;
48-
const matches = node.getText().match(regex);
49-
flagOpts = {
50-
isMedia:true,
51-
text:matches?.[0].toString()!
52-
};
53-
}
54-
55-
if (node instanceof nodes.Selector) {
56-
hover = {
57-
contents: this.selectorPrinting.selectorToMarkedString(<nodes.Selector>node, flagOpts!),
58-
range: getRange(node)
59-
};
60-
break;
61-
}
62-
63-
if (node instanceof nodes.SimpleSelector) {
64-
/**
65-
* Some sass specific at rules such as `@at-root` are parsed as `SimpleSelector`
66-
*/
67-
if (!startsWith(node.getText(), '@')) {
68-
hover = {
69-
contents: this.selectorPrinting.simpleSelectorToMarkedString(<nodes.SimpleSelector>node),
70-
range: getRange(node)
71-
};
72-
}
73-
break;
74-
}
75-
76-
if (node instanceof nodes.Declaration) {
77-
const propertyName = node.getFullPropertyName();
78-
const entry = this.cssDataManager.getProperty(propertyName);
79-
if (entry) {
80-
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
81-
if (contents) {
82-
hover = {
83-
contents,
84-
range: getRange(node)
85-
};
86-
} else {
87-
hover = null;
88-
}
89-
}
90-
continue;
91-
}
92-
93-
if (node instanceof nodes.UnknownAtRule) {
94-
const atRuleName = node.getText();
95-
const entry = this.cssDataManager.getAtDirective(atRuleName);
96-
if (entry) {
97-
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
98-
if (contents) {
99-
hover = {
100-
contents,
101-
range: getRange(node)
102-
};
103-
} else {
104-
hover = null;
105-
}
106-
}
107-
continue;
108-
}
109-
110-
if (node instanceof nodes.Node && node.type === nodes.NodeType.PseudoSelector) {
111-
const selectorName = node.getText();
112-
const entry =
113-
selectorName.slice(0, 2) === '::'
114-
? this.cssDataManager.getPseudoElement(selectorName)
115-
: this.cssDataManager.getPseudoClass(selectorName);
116-
if (entry) {
117-
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
118-
if (contents) {
119-
hover = {
120-
contents,
121-
range: getRange(node)
122-
};
123-
} else {
124-
hover = null;
125-
}
126-
}
127-
continue;
128-
}
129-
}
130-
131-
132-
if (hover) {
133-
hover.contents = this.convertContents(hover.contents);
134-
}
135-
136-
return hover;
137-
}
138-
139-
private convertContents(contents: MarkupContent | MarkedString | MarkedString[]): MarkupContent | MarkedString | MarkedString[] {
140-
if (!this.doesSupportMarkdown()) {
141-
if (typeof contents === 'string') {
142-
return contents;
143-
}
144-
// MarkupContent
145-
else if ('kind' in contents) {
146-
return {
147-
kind: 'plaintext',
148-
value: contents.value
149-
};
150-
}
151-
// MarkedString[]
152-
else if (Array.isArray(contents)) {
153-
return contents.map(c => {
154-
return typeof c === 'string' ? c : c.value;
155-
});
156-
}
157-
// MarkedString
158-
else {
159-
return contents.value;
160-
}
161-
}
162-
163-
return contents;
164-
}
165-
166-
private doesSupportMarkdown() {
167-
if (!isDefined(this.supportsMarkdown)) {
168-
if (!isDefined(this.clientCapabilities)) {
169-
this.supportsMarkdown = true;
170-
return this.supportsMarkdown;
171-
}
172-
173-
const hover = this.clientCapabilities.textDocument && this.clientCapabilities.textDocument.hover;
174-
this.supportsMarkdown = hover && hover.contentFormat && Array.isArray(hover.contentFormat) && hover.contentFormat.indexOf(MarkupKind.Markdown) !== -1;
175-
}
176-
return <boolean>this.supportsMarkdown;
177-
}
16+
private supportsMarkdown: boolean | undefined;
17+
private readonly selectorPrinting: SelectorPrinting;
18+
private defaultSettings?: HoverSettings;
19+
20+
constructor(
21+
private readonly clientCapabilities: ClientCapabilities | undefined,
22+
private readonly cssDataManager: CSSDataManager,
23+
) {
24+
this.selectorPrinting = new SelectorPrinting(cssDataManager);
25+
}
26+
27+
public configure(settings: HoverSettings | undefined) {
28+
this.defaultSettings = settings;
29+
}
30+
31+
public doHover(document: TextDocument, position: Position, stylesheet: nodes.Stylesheet, settings = this.defaultSettings): Hover | null {
32+
function getRange(node: nodes.Node) {
33+
return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
34+
}
35+
const offset = document.offsetAt(position);
36+
const nodepath = nodes.getNodePath(stylesheet, offset);
37+
38+
/**
39+
* nodepath is top-down
40+
* Build up the hover by appending inner node's information
41+
*/
42+
let hover: Hover | null = null;
43+
let flagOpts: { text: string; isMedia: boolean };
44+
45+
for (let i = 0; i < nodepath.length; i++) {
46+
const node = nodepath[i];
47+
48+
if (node instanceof nodes.Media) {
49+
const regex = /@media[^\{]+/g;
50+
const matches = node.getText().match(regex);
51+
flagOpts = {
52+
isMedia: true,
53+
text: matches?.[0]!,
54+
};
55+
}
56+
57+
if (node instanceof nodes.Selector) {
58+
hover = {
59+
contents: this.selectorPrinting.selectorToMarkedString(<nodes.Selector>node, flagOpts!),
60+
range: getRange(node),
61+
};
62+
break;
63+
}
64+
65+
if (node instanceof nodes.SimpleSelector) {
66+
/**
67+
* Some sass specific at rules such as `@at-root` are parsed as `SimpleSelector`
68+
*/
69+
if (!startsWith(node.getText(), '@')) {
70+
hover = {
71+
contents: this.selectorPrinting.simpleSelectorToMarkedString(<nodes.SimpleSelector>node),
72+
range: getRange(node),
73+
};
74+
}
75+
break;
76+
}
77+
78+
if (node instanceof nodes.Declaration) {
79+
const propertyName = node.getFullPropertyName();
80+
const entry = this.cssDataManager.getProperty(propertyName);
81+
if (entry) {
82+
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
83+
if (contents) {
84+
hover = {
85+
contents,
86+
range: getRange(node),
87+
};
88+
} else {
89+
hover = null;
90+
}
91+
}
92+
continue;
93+
}
94+
95+
if (node instanceof nodes.UnknownAtRule) {
96+
const atRuleName = node.getText();
97+
const entry = this.cssDataManager.getAtDirective(atRuleName);
98+
if (entry) {
99+
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
100+
if (contents) {
101+
hover = {
102+
contents,
103+
range: getRange(node),
104+
};
105+
} else {
106+
hover = null;
107+
}
108+
}
109+
continue;
110+
}
111+
112+
if (node instanceof nodes.Node && node.type === nodes.NodeType.PseudoSelector) {
113+
const selectorName = node.getText();
114+
const entry = selectorName.slice(0, 2) === '::' ? this.cssDataManager.getPseudoElement(selectorName) : this.cssDataManager.getPseudoClass(selectorName);
115+
if (entry) {
116+
const contents = languageFacts.getEntryDescription(entry, this.doesSupportMarkdown(), settings);
117+
if (contents) {
118+
hover = {
119+
contents,
120+
range: getRange(node),
121+
};
122+
} else {
123+
hover = null;
124+
}
125+
}
126+
continue;
127+
}
128+
}
129+
130+
if (hover) {
131+
hover.contents = this.convertContents(hover.contents);
132+
}
133+
134+
return hover;
135+
}
136+
137+
private convertContents(contents: MarkupContent | MarkedString | MarkedString[]): MarkupContent | MarkedString | MarkedString[] {
138+
if (!this.doesSupportMarkdown()) {
139+
if (typeof contents === 'string') {
140+
return contents;
141+
}
142+
// MarkupContent
143+
else if ('kind' in contents) {
144+
return {
145+
kind: 'plaintext',
146+
value: contents.value,
147+
};
148+
}
149+
// MarkedString[]
150+
else if (Array.isArray(contents)) {
151+
return contents.map((c) => {
152+
return typeof c === 'string' ? c : c.value;
153+
});
154+
}
155+
// MarkedString
156+
else {
157+
return contents.value;
158+
}
159+
}
160+
161+
return contents;
162+
}
163+
164+
private doesSupportMarkdown() {
165+
if (!isDefined(this.supportsMarkdown)) {
166+
if (!isDefined(this.clientCapabilities)) {
167+
this.supportsMarkdown = true;
168+
return this.supportsMarkdown;
169+
}
170+
171+
const hover = this.clientCapabilities.textDocument && this.clientCapabilities.textDocument.hover;
172+
this.supportsMarkdown = hover && hover.contentFormat && Array.isArray(hover.contentFormat) && hover.contentFormat.indexOf(MarkupKind.Markdown) !== -1;
173+
}
174+
return <boolean>this.supportsMarkdown;
175+
}
178176
}

0 commit comments

Comments
 (0)